- Timestamp:
- Jul 22, 2011 2:35:39 PM (14 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/src-server/MachineImplCloneVM.cpp
r38061 r38116 25 25 #include <iprt/dir.h> 26 26 #include <iprt/cpp/utils.h> 27 #ifdef DEBUG_poetzsch 28 # include <iprt/stream.h> 29 #endif 27 30 28 31 #include <VBox/com/list.h> … … 94 97 95 98 /* Private helper methods */ 99 100 /* MachineCloneVM::start helper: */ 96 101 HRESULT createMachineList(const ComPtr<ISnapshot> &pSnapshot, RTCList< ComObjPtr<Machine> > &machineList) const; 102 inline void updateProgressStats(MEDIUMTASKCHAIN &mtc, bool fAttachLinked, ULONG &uCount, ULONG &uTotalWeight) const; 103 inline HRESULT addSaveState(const ComObjPtr<Machine> &machine, ULONG &uCount, ULONG &uTotalWeight); 104 inline HRESULT queryBaseName(const ComPtr<IMedium> &pMedium, Utf8Str &strBaseName) const; 105 HRESULT queryMediasForMachineState(const RTCList<ComObjPtr<Machine> > &machineList, bool fAttachLinked, ULONG &uCount, ULONG &uTotalWeight); 106 HRESULT queryMediasForMachineAndChildStates(const RTCList<ComObjPtr<Machine> > &machineList, bool fAttachLinked, ULONG &uCount, ULONG &uTotalWeight); 107 HRESULT queryMediasForAllStates(const RTCList<ComObjPtr<Machine> > &machineList, bool fAttachLinked, ULONG &uCount, ULONG &uTotalWeight); 108 109 /* MachineCloneVM::run helper: */ 97 110 settings::Snapshot findSnapshot(settings::MachineConfigFile *pMCF, const settings::SnapshotsList &snl, const Guid &id) const; 98 111 void updateMACAddresses(settings::NetworkAdaptersList &nwl) const; … … 137 150 { 138 151 rc = createMachineList(sfaChilds[i], machineList); 152 if (FAILED(rc)) return rc; 153 } 154 155 return rc; 156 } 157 158 void MachineCloneVMPrivate::updateProgressStats(MEDIUMTASKCHAIN &mtc, bool fAttachLinked, ULONG &uCount, ULONG &uTotalWeight) const 159 { 160 if (fAttachLinked) 161 { 162 /* Implicit diff creation as part of attach is a pretty cheap 163 * operation, and does only need one operation per attachment. */ 164 ++uCount; 165 uTotalWeight += 1; /* 1MB per attachment */ 166 } 167 else 168 { 169 /* Currently the copying of diff images involves reading at least 170 * the biggest parent in the previous chain. So even if the new 171 * diff image is small in size, it could need some time to create 172 * it. Adding the biggest size in the chain should balance this a 173 * little bit more, i.e. the weight is the sum of the data which 174 * needs to be read and written. */ 175 uint64_t uMaxSize = 0; 176 for (size_t e = mtc.chain.size(); e > 0; --e) 177 { 178 MEDIUMTASK &mt = mtc.chain.at(e - 1); 179 mt.uWeight += uMaxSize; 180 181 /* Calculate progress data */ 182 ++uCount; 183 uTotalWeight += mt.uWeight; 184 185 /* Save the max size for better weighting of diff image 186 * creation. */ 187 uMaxSize = RT_MAX(uMaxSize, mt.uWeight); 188 } 189 } 190 } 191 192 HRESULT MachineCloneVMPrivate::addSaveState(const ComObjPtr<Machine> &machine, ULONG &uCount, ULONG &uTotalWeight) 193 { 194 Bstr bstrSrcSaveStatePath; 195 HRESULT rc = machine->COMGETTER(StateFilePath)(bstrSrcSaveStatePath.asOutParam()); 196 if (FAILED(rc)) return rc; 197 if (!bstrSrcSaveStatePath.isEmpty()) 198 { 199 SAVESTATETASK sst; 200 sst.snapshotUuid = machine->getSnapshotId(); 201 sst.strSaveStateFile = bstrSrcSaveStatePath; 202 uint64_t cbSize; 203 int vrc = RTFileQuerySize(sst.strSaveStateFile.c_str(), &cbSize); 204 if (RT_FAILURE(vrc)) 205 return p->setError(VBOX_E_IPRT_ERROR, p->tr("Could not query file size of '%s' (%Rrc)"), sst.strSaveStateFile.c_str(), vrc); 206 /* same rule as above: count both the data which needs to 207 * be read and written */ 208 sst.uWeight = 2 * (cbSize + _1M - 1) / _1M; 209 llSaveStateFiles.append(sst); 210 ++uCount; 211 uTotalWeight += sst.uWeight; 212 } 213 return S_OK; 214 } 215 216 HRESULT MachineCloneVMPrivate::queryBaseName(const ComPtr<IMedium> &pMedium, Utf8Str &strBaseName) const 217 { 218 ComPtr<IMedium> pBaseMedium; 219 HRESULT rc = pMedium->COMGETTER(Base)(pBaseMedium.asOutParam()); 220 if (FAILED(rc)) return rc; 221 Bstr bstrBaseName; 222 rc = pBaseMedium->COMGETTER(Name)(bstrBaseName.asOutParam()); 223 if (FAILED(rc)) return rc; 224 strBaseName = bstrBaseName; 225 return rc; 226 } 227 228 HRESULT MachineCloneVMPrivate::queryMediasForMachineState(const RTCList<ComObjPtr<Machine> > &machineList, bool fAttachLinked, ULONG &uCount, ULONG &uTotalWeight) 229 { 230 /* This mode is pretty straightforward. We didn't need to know about any 231 * parent/children relationship and therefor simply adding all directly 232 * attached images of the source VM as cloning targets. The IMedium code 233 * take than care to merge any (possibly) existing parents into the new 234 * image. */ 235 HRESULT rc = S_OK; 236 for (size_t i = 0; i < machineList.size(); ++i) 237 { 238 const ComObjPtr<Machine> &machine = machineList.at(i); 239 /* If this is the Snapshot Machine we want to clone, we need to 240 * create a new diff file for the new "current state". */ 241 const bool fCreateDiffs = (machine == pOldMachineState); 242 /* Add all attachments of the different machines to a worker list. */ 243 SafeIfaceArray<IMediumAttachment> sfaAttachments; 244 rc = machine->COMGETTER(MediumAttachments)(ComSafeArrayAsOutParam(sfaAttachments)); 245 if (FAILED(rc)) return rc; 246 for (size_t a = 0; a < sfaAttachments.size(); ++a) 247 { 248 const ComPtr<IMediumAttachment> &pAtt = sfaAttachments[a]; 249 DeviceType_T type; 250 rc = pAtt->COMGETTER(Type)(&type); 251 if (FAILED(rc)) return rc; 252 253 /* Only harddisk's are of interest. */ 254 if (type != DeviceType_HardDisk) 255 continue; 256 257 /* Valid medium attached? */ 258 ComPtr<IMedium> pSrcMedium; 259 rc = pAtt->COMGETTER(Medium)(pSrcMedium.asOutParam()); 260 if (FAILED(rc)) return rc; 261 if (pSrcMedium.isNull()) 262 continue; 263 264 /* Create the medium task chain. In this case it will always 265 * contain one image only. */ 266 MEDIUMTASKCHAIN mtc; 267 mtc.fCreateDiffs = fCreateDiffs; 268 mtc.fAttachLinked = fAttachLinked; 269 270 /* Refresh the state so that the file size get read. */ 271 MediumState_T e; 272 rc = pSrcMedium->RefreshState(&e); 273 if (FAILED(rc)) return rc; 274 LONG64 lSize; 275 rc = pSrcMedium->COMGETTER(Size)(&lSize); 276 if (FAILED(rc)) return rc; 277 278 MEDIUMTASK mt; 279 280 /* Save the base name. */ 281 rc = queryBaseName(pSrcMedium, mt.strBaseName); 282 if (FAILED(rc)) return rc; 283 284 /* Save the current medium, for later cloning. */ 285 mt.pMedium = pSrcMedium; 286 if (fAttachLinked) 287 mt.uWeight = 0; /* dummy */ 288 else 289 mt.uWeight = (lSize + _1M - 1) / _1M; 290 mtc.chain.append(mt); 291 292 /* Update the progress info. */ 293 updateProgressStats(mtc, fAttachLinked, uCount, uTotalWeight); 294 /* Append the list of images which have to be cloned. */ 295 llMedias.append(mtc); 296 } 297 /* Add the save state files of this machine if there is one. */ 298 rc = addSaveState(machine, uCount, uTotalWeight); 299 if (FAILED(rc)) return rc; 300 } 301 302 return rc; 303 } 304 305 HRESULT MachineCloneVMPrivate::queryMediasForMachineAndChildStates(const RTCList<ComObjPtr<Machine> > &machineList, bool fAttachLinked, ULONG &uCount, ULONG &uTotalWeight) 306 { 307 /* This is basically a three step approach. First select all medias 308 * directly or indirectly involved in the clone. Second create a histogram 309 * of the usage of all that medias. Third select the medias which are 310 * directly attached or have more than one directly/indirectly used child 311 * in the new clone. Step one and two are done in the first loop. 312 * 313 * Example of the histogram counts after going through 3 attachments from 314 * bottom to top: 315 * 316 * 3 317 * | 318 * -> 3 319 * / \ 320 * 2 1 <- 321 * / 322 * -> 2 323 * / \ 324 * -> 1 1 325 * \ 326 * 1 <- 327 * 328 * Whenever the histogram count is changing compared to the previous one we 329 * need to include that image in the cloning step (Marked with <-). If we 330 * start at zero even the directly attached images are automatically 331 * included. 332 * 333 * Note: This still leads to media chains which can have the same medium 334 * included. This case is handled in "run" and therefor not critical, but 335 * it leads to wrong progress infos which isn't nice. */ 336 337 HRESULT rc = S_OK; 338 std::map<ComPtr<IMedium>, uint32_t> mediaHist; /* Our usage histogram for the medias */ 339 for (size_t i = 0; i < machineList.size(); ++i) 340 { 341 const ComObjPtr<Machine> &machine = machineList.at(i); 342 /* If this is the Snapshot Machine we want to clone, we need to 343 * create a new diff file for the new "current state". */ 344 const bool fCreateDiffs = (machine == pOldMachineState); 345 /* Add all attachments (and their parents) of the different 346 * machines to a worker list. */ 347 SafeIfaceArray<IMediumAttachment> sfaAttachments; 348 rc = machine->COMGETTER(MediumAttachments)(ComSafeArrayAsOutParam(sfaAttachments)); 349 if (FAILED(rc)) return rc; 350 for (size_t a = 0; a < sfaAttachments.size(); ++a) 351 { 352 const ComPtr<IMediumAttachment> &pAtt = sfaAttachments[a]; 353 DeviceType_T type; 354 rc = pAtt->COMGETTER(Type)(&type); 355 if (FAILED(rc)) return rc; 356 357 /* Only harddisk's are of interest. */ 358 if (type != DeviceType_HardDisk) 359 continue; 360 361 /* Valid medium attached? */ 362 ComPtr<IMedium> pSrcMedium; 363 rc = pAtt->COMGETTER(Medium)(pSrcMedium.asOutParam()); 364 if (FAILED(rc)) return rc; 365 366 if (pSrcMedium.isNull()) 367 continue; 368 369 MEDIUMTASKCHAIN mtc; 370 mtc.fCreateDiffs = fCreateDiffs; 371 mtc.fAttachLinked = fAttachLinked; 372 373 while (!pSrcMedium.isNull()) 374 { 375 /* Build a histogram of used medias and the parent chain. */ 376 ++mediaHist[pSrcMedium]; 377 378 /* Refresh the state so that the file size get read. */ 379 MediumState_T e; 380 rc = pSrcMedium->RefreshState(&e); 381 if (FAILED(rc)) return rc; 382 LONG64 lSize; 383 rc = pSrcMedium->COMGETTER(Size)(&lSize); 384 if (FAILED(rc)) return rc; 385 386 MEDIUMTASK mt; 387 mt.pMedium = pSrcMedium; 388 mt.uWeight = (lSize + _1M - 1) / _1M; 389 mtc.chain.append(mt); 390 391 /* Query next parent. */ 392 rc = pSrcMedium->COMGETTER(Parent)(pSrcMedium.asOutParam()); 393 if (FAILED(rc)) return rc; 394 } 395 396 llMedias.append(mtc); 397 } 398 /* Add the save state files of this machine if there is one. */ 399 rc = addSaveState(machine, uCount, uTotalWeight); 400 if (FAILED(rc)) return rc; 401 } 402 #ifdef DEBUG_poetzsch 403 /* Print the histogram */ 404 std::map<ComPtr<IMedium>, uint32_t>::iterator it; 405 for (it = mediaHist.begin(); it != mediaHist.end(); ++it) 406 { 407 Bstr bstrSrcName; 408 rc = (*it).first->COMGETTER(Name)(bstrSrcName.asOutParam()); 409 if (FAILED(rc)) return rc; 410 RTPrintf("%ls: %d\n", bstrSrcName.raw(), (*it).second); 411 } 412 #endif 413 /* Go over every medium in the list and check if it either a directly 414 * attached disk or has more than one children. If so it needs to be 415 * replicated. Also we have to make sure that any direct or indirect 416 * children knows of the new parent (which doesn't necessarily mean it 417 * is a direct children in the source chain). */ 418 for (size_t i = 0; i < llMedias.size(); ++i) 419 { 420 MEDIUMTASKCHAIN &mtc = llMedias.at(i); 421 RTCList<MEDIUMTASK> newChain; 422 uint32_t used = 0; 423 for (size_t a = 0; a < mtc.chain.size(); ++a) 424 { 425 const MEDIUMTASK &mt = mtc.chain.at(a); 426 uint32_t hist = mediaHist[mt.pMedium]; 427 #ifdef DEBUG_poetzsch 428 Bstr bstrSrcName; 429 rc = mt.pMedium->COMGETTER(Name)(bstrSrcName.asOutParam()); 430 if (FAILED(rc)) return rc; 431 RTPrintf("%ls: %d (%d)\n", bstrSrcName.raw(), hist, used); 432 #endif 433 /* Check if there is a "step" in the histogram when going the chain 434 * upwards. If so, we need this image, cause there is another leave 435 * from here in the cloned VM. */ 436 if (hist > used) 437 { 438 newChain.append(mt); 439 used = hist; 440 } 441 } 442 /* Make sure we always using the old base name as new base name, even 443 * if the base is a differencing image in the source VM (with the UUID 444 * as name). */ 445 rc = queryBaseName(newChain.last().pMedium, newChain.last().strBaseName); 446 if (FAILED(rc)) return rc; 447 /* Update the old medium chain with the updated one. */ 448 mtc.chain = newChain; 449 /* Update the progress info. */ 450 updateProgressStats(mtc, fAttachLinked, uCount, uTotalWeight); 451 } 452 453 return rc; 454 } 455 456 HRESULT MachineCloneVMPrivate::queryMediasForAllStates(const RTCList<ComObjPtr<Machine> > &machineList, bool fAttachLinked, ULONG &uCount, ULONG &uTotalWeight) 457 { 458 /* In this case we create a exact copy of the original VM. This means just 459 * adding all directly and indirectly attached disk images to the worker 460 * list. */ 461 HRESULT rc = S_OK; 462 for (size_t i = 0; i < machineList.size(); ++i) 463 { 464 const ComObjPtr<Machine> &machine = machineList.at(i); 465 /* If this is the Snapshot Machine we want to clone, we need to 466 * create a new diff file for the new "current state". */ 467 const bool fCreateDiffs = (machine == pOldMachineState); 468 /* Add all attachments (and their parents) of the different 469 * machines to a worker list. */ 470 SafeIfaceArray<IMediumAttachment> sfaAttachments; 471 rc = machine->COMGETTER(MediumAttachments)(ComSafeArrayAsOutParam(sfaAttachments)); 472 if (FAILED(rc)) return rc; 473 for (size_t a = 0; a < sfaAttachments.size(); ++a) 474 { 475 const ComPtr<IMediumAttachment> &pAtt = sfaAttachments[a]; 476 DeviceType_T type; 477 rc = pAtt->COMGETTER(Type)(&type); 478 if (FAILED(rc)) return rc; 479 480 /* Only harddisk's are of interest. */ 481 if (type != DeviceType_HardDisk) 482 continue; 483 484 /* Valid medium attached? */ 485 ComPtr<IMedium> pSrcMedium; 486 rc = pAtt->COMGETTER(Medium)(pSrcMedium.asOutParam()); 487 if (FAILED(rc)) return rc; 488 if (pSrcMedium.isNull()) 489 continue; 490 491 /* Build up a child->parent list of this attachment. (Note: we are 492 * not interested of any child's not attached to this VM. So this 493 * will not create a full copy of the base/child relationship.) */ 494 MEDIUMTASKCHAIN mtc; 495 mtc.fCreateDiffs = fCreateDiffs; 496 mtc.fAttachLinked = fAttachLinked; 497 498 while (!pSrcMedium.isNull()) 499 { 500 /* Refresh the state so that the file size get read. */ 501 MediumState_T e; 502 rc = pSrcMedium->RefreshState(&e); 503 if (FAILED(rc)) return rc; 504 LONG64 lSize; 505 rc = pSrcMedium->COMGETTER(Size)(&lSize); 506 if (FAILED(rc)) return rc; 507 508 /* Save the current medium, for later cloning. */ 509 MEDIUMTASK mt; 510 mt.pMedium = pSrcMedium; 511 mt.uWeight = (lSize + _1M - 1) / _1M; 512 mtc.chain.append(mt); 513 514 /* Query next parent. */ 515 rc = pSrcMedium->COMGETTER(Parent)(pSrcMedium.asOutParam()); 516 if (FAILED(rc)) return rc; 517 } 518 /* Update the progress info. */ 519 updateProgressStats(mtc, fAttachLinked, uCount, uTotalWeight); 520 /* Append the list of images which have to be cloned. */ 521 llMedias.append(mtc); 522 } 523 /* Add the save state files of this machine if there is one. */ 524 rc = addSaveState(machine, uCount, uTotalWeight); 139 525 if (FAILED(rc)) return rc; 140 526 } … … 328 714 } 329 715 rc = pSnapshot->COMGETTER(Parent)(pSnapshot.asOutParam()); 716 if (FAILED(rc)) throw rc; 330 717 } 331 718 } … … 389 776 } 390 777 391 /* Go over every machine and walk over every attachment this machine has. */ 778 /* If we want to create a linked clone just attach the medium 779 * associated with the snapshot. The rest is taken care of by 780 * attach already, so no need to duplicate this. */ 781 782 /* We have different approaches for getting the medias which needs to 783 * be replicated based on the clone mode the user requested (this is 784 * mostly about the full clone mode). 785 * MachineState: 786 * - Only the images which are directly attached to an source VM will 787 * be cloned. Any parent disks in the original chain will be merged 788 * into the final cloned disk. 789 * MachineAndChildStates: 790 * - In this case we search for images which have more than one 791 * children in the cloned VM or are directly attached to the new VM. 792 * All others will be merged into the remaining images which are 793 * cloned. 794 * This case is the most complicated one and needs several iterations 795 * to make sure we are only cloning images which are really 796 * necessary. 797 * AllStates: 798 * - All disks which are directly or indirectly attached to the 799 * original VM are cloned. 800 * 801 * Note: If you change something generic on one if the methods its 802 * likely that it need changed in the others as well! */ 392 803 ULONG uCount = 2; /* One init task and the machine creation. */ 393 804 ULONG uTotalWeight = 2; /* The init task and the machine creation is worth one. */ 394 for (size_t i = 0; i < machineList.size(); ++i) 395 { 396 ComObjPtr<Machine> machine = machineList.at(i); 397 /* If this is the Snapshot Machine we want to clone, we need to 398 * create a new diff file for the new "current state". */ 399 bool fCreateDiffs = false; 400 if (machine == d->pOldMachineState) 401 fCreateDiffs = true; 402 /* If we want to create a linked clone just attach the medium 403 * associated with the snapshot. The rest is taken care of by 404 * attach already, so no need to duplicate this. */ 405 bool fAttachLinked = false; 406 if (d->options.contains(CloneOptions_Link)) 407 fAttachLinked = true; 408 SafeIfaceArray<IMediumAttachment> sfaAttachments; 409 rc = machine->COMGETTER(MediumAttachments)(ComSafeArrayAsOutParam(sfaAttachments)); 410 if (FAILED(rc)) throw rc; 411 /* Add all attachments (and their parents) of the different 412 * machines to a worker list. */ 413 for (size_t a = 0; a < sfaAttachments.size(); ++a) 414 { 415 const ComPtr<IMediumAttachment> &pAtt = sfaAttachments[a]; 416 DeviceType_T type; 417 rc = pAtt->COMGETTER(Type)(&type); 418 if (FAILED(rc)) throw rc; 419 420 /* Only harddisk's are of interest. */ 421 if (type != DeviceType_HardDisk) 422 continue; 423 424 /* Valid medium attached? */ 425 ComPtr<IMedium> pSrcMedium; 426 rc = pAtt->COMGETTER(Medium)(pSrcMedium.asOutParam()); 427 if (FAILED(rc)) throw rc; 428 if (pSrcMedium.isNull()) 429 continue; 430 431 /* Build up a child->parent list of this attachment. (Note: we are 432 * not interested of any child's not attached to this VM. So this 433 * will not create a full copy of the base/child relationship.) */ 434 MEDIUMTASKCHAIN mtc; 435 mtc.fCreateDiffs = fCreateDiffs; 436 mtc.fAttachLinked = fAttachLinked; 437 438 /* If the current state without any snapshots is cloned, we 439 * don't need any diff images in the new clone. Add the last 440 * medium to the list of medias to create only (the clone 441 * operation of IMedium will create a merged copy 442 * automatically). */ 443 if (d->mode == CloneMode_MachineState) 444 { 445 /* Refresh the state so that the file size get read. */ 446 MediumState_T e; 447 rc = pSrcMedium->RefreshState(&e); 448 if (FAILED(rc)) throw rc; 449 LONG64 lSize; 450 rc = pSrcMedium->COMGETTER(Size)(&lSize); 451 if (FAILED(rc)) throw rc; 452 453 ComPtr<IMedium> pBaseMedium; 454 rc = pSrcMedium->COMGETTER(Base)(pBaseMedium.asOutParam()); 455 if (FAILED(rc)) throw rc; 456 457 MEDIUMTASK mt; 458 459 Bstr bstrBaseName; 460 rc = pBaseMedium->COMGETTER(Name)(bstrBaseName.asOutParam()); 461 if (FAILED(rc)) throw rc; 462 463 /* Save the base name. */ 464 mt.strBaseName = bstrBaseName; 465 466 /* Save the current medium, for later cloning. */ 467 mt.pMedium = pSrcMedium; 468 if (fAttachLinked) 469 mt.uWeight = 0; /* dummy */ 470 else 471 mt.uWeight = (lSize + _1M - 1) / _1M; 472 mtc.chain.append(mt); 473 } 474 else 475 { 476 /** @todo r=klaus this puts way too many images in the list 477 * when cloning a snapshot (sub)tree, which means that more 478 * images are cloned than necessary. It is just the easiest 479 * way to get a working VM, as getting the image 480 * parent/child relationships right for only the bare 481 * minimum cloning is rather tricky. */ 482 while (!pSrcMedium.isNull()) 483 { 484 /* Refresh the state so that the file size get read. */ 485 MediumState_T e; 486 rc = pSrcMedium->RefreshState(&e); 487 if (FAILED(rc)) throw rc; 488 LONG64 lSize; 489 rc = pSrcMedium->COMGETTER(Size)(&lSize); 490 if (FAILED(rc)) throw rc; 491 492 /* Save the current medium, for later cloning. */ 493 MEDIUMTASK mt; 494 mt.pMedium = pSrcMedium; 495 mt.uWeight = (lSize + _1M - 1) / _1M; 496 mtc.chain.append(mt); 497 498 /* Query next parent. */ 499 rc = pSrcMedium->COMGETTER(Parent)(pSrcMedium.asOutParam()); 500 if (FAILED(rc)) throw rc; 501 } 502 } 503 504 if (fAttachLinked) 505 { 506 /* Implicit diff creation as part of attach is a pretty cheap 507 * operation, and does only need one operation per attachment. */ 508 ++uCount; 509 uTotalWeight += 1; /* 1MB per attachment */ 510 } 511 else 512 { 513 /* Currently the copying of diff images involves reading at least 514 * the biggest parent in the previous chain. So even if the new 515 * diff image is small in size, it could need some time to create 516 * it. Adding the biggest size in the chain should balance this a 517 * little bit more, i.e. the weight is the sum of the data which 518 * needs to be read and written. */ 519 uint64_t uMaxSize = 0; 520 for (size_t e = mtc.chain.size(); e > 0; --e) 521 { 522 MEDIUMTASK &mt = mtc.chain.at(e - 1); 523 mt.uWeight += uMaxSize; 524 525 /* Calculate progress data */ 526 ++uCount; 527 uTotalWeight += mt.uWeight; 528 529 /* Save the max size for better weighting of diff image 530 * creation. */ 531 uMaxSize = RT_MAX(uMaxSize, mt.uWeight); 532 } 533 } 534 d->llMedias.append(mtc); 535 } 536 Bstr bstrSrcSaveStatePath; 537 rc = machine->COMGETTER(StateFilePath)(bstrSrcSaveStatePath.asOutParam()); 538 if (FAILED(rc)) throw rc; 539 if (!bstrSrcSaveStatePath.isEmpty()) 540 { 541 SAVESTATETASK sst; 542 sst.snapshotUuid = machine->getSnapshotId(); 543 sst.strSaveStateFile = bstrSrcSaveStatePath; 544 uint64_t cbSize; 545 int vrc = RTFileQuerySize(sst.strSaveStateFile.c_str(), &cbSize); 546 if (RT_FAILURE(vrc)) 547 throw p->setError(VBOX_E_IPRT_ERROR, p->tr("Could not query file size of '%s' (%Rrc)"), sst.strSaveStateFile.c_str(), vrc); 548 /* same rule as above: count both the data which needs to 549 * be read and written */ 550 sst.uWeight = 2 * (cbSize + _1M - 1) / _1M; 551 d->llSaveStateFiles.append(sst); 552 ++uCount; 553 uTotalWeight += sst.uWeight; 554 } 555 } 556 805 bool fAttachLinked = d->options.contains(CloneOptions_Link); /* Linked clones requested? */ 806 switch (d->mode) 807 { 808 case CloneMode_MachineState: d->queryMediasForMachineState(machineList, fAttachLinked, uCount, uTotalWeight); break; 809 case CloneMode_MachineAndChildStates: d->queryMediasForMachineAndChildStates(machineList, fAttachLinked, uCount, uTotalWeight); break; 810 case CloneMode_AllStates: d->queryMediasForAllStates(machineList, fAttachLinked, uCount, uTotalWeight); break; 811 } 812 813 /* Now create the progress project, so the user knows whats going on. */ 557 814 rc = d->pProgress.createObject(); 558 815 if (FAILED(rc)) throw rc;
Note:
See TracChangeset
for help on using the changeset viewer.