Changeset 37449 in vbox for trunk/src/VBox/Main
- Timestamp:
- Jun 14, 2011 4:34:16 PM (13 years ago)
- Location:
- trunk/src/VBox/Main
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/idl/VirtualBox.xidl
r37447 r37449 3513 3513 </interface> 3514 3514 3515 <enum 3516 name="CloneMode" extends="$unknown" 3517 uuid="A7A159FE-5096-4B8D-8C3C-D033CB0B35A8" 3518 > 3519 3520 <desc> 3521 Clone mode, used with <link to="IMachine::cloneTo" />. 3522 </desc> 3523 3524 <const name="MachineState" value="1"> 3525 <desc>Clone the state of the machine.</desc> 3526 </const> 3527 <const name="MachineAndChildStates" value="2"> 3528 <desc>Clone the state of the machine and if this machine object has child snapshots the state of this childs.</desc> 3529 </const> 3530 <const name="AllStates" value="3"> 3531 <desc>Clone all states (including all snapshots) of the machine, regardless of the machine object used.</desc> 3532 </const> 3533 3534 </enum> 3535 3515 3536 3516 3537 <interface 3517 3538 name="IMachine" extends="$unknown" 3518 uuid=" 84208466-c072-4e64-b993-c35c096cc837"3539 uuid="5A398458-266D-4DCD-9745-0886AEBD761B" 3519 3540 wsmap="managed" 3520 3541 > … … 5963 5984 <desc>Target machine object.</desc> 5964 5985 </param> 5986 <param name="mode" type="CloneMode" dir="in"> 5987 <desc>Which states should be cloned.</desc> 5988 </param> 5965 5989 <param name="fullClone" type="boolean" dir="in"> 5966 5990 <desc>Selects whether a full or linked clone is created.</desc> … … 9129 9153 <method name="waitForAsyncProgressCompletion"> 9130 9154 <desc> 9131 Waits until the other task is completed (including all9132 sub-operations) and forward all changes from the other progress to9133 this progress. This means sub-operation number, description, percent9134 and so on.9135 9136 You have to take care on setting up at least the same count on9137 sub-operations in this progress object like there are in the other9138 progress object.9139 9140 If the other progress object supports cancel and this object gets any9141 cancel request (when here enabled as well), it will be forwarded to9142 the other progress object.9143 9144 If there is an error in the other progress, this error isn't9145 automatically transfered to this progress object. So you have to9146 check any operation error within the other progress object, after9147 this method returns.9148 </desc> 9149 9150 <param name="pProgressAsync" type="IProgress" dir="in">9151 <desc>9152 The progress object of the asynchrony process.9153 </desc>9154 </param>9155 Waits until the other task is completed (including all 9156 sub-operations) and forward all changes from the other progress to 9157 this progress. This means sub-operation number, description, percent 9158 and so on. 9159 9160 You have to take care on setting up at least the same count on 9161 sub-operations in this progress object like there are in the other 9162 progress object. 9163 9164 If the other progress object supports cancel and this object gets any 9165 cancel request (when here enabled as well), it will be forwarded to 9166 the other progress object. 9167 9168 If there is an error in the other progress, this error isn't 9169 automatically transfered to this progress object. So you have to 9170 check any operation error within the other progress object, after 9171 this method returns. 9172 </desc> 9173 9174 <param name="pProgressAsync" type="IProgress" dir="in"> 9175 <desc> 9176 The progress object of the asynchrony process. 9177 </desc> 9178 </param> 9155 9179 </method> 9156 9180 … … 9178 9202 <interface 9179 9203 name="ISnapshot" extends="$unknown" 9180 uuid=" 1a2d0551-58a4-4107-857e-ef414fc42ffc"9204 uuid="0472823b-c6e7-472a-8e9f-d732e86b8463" 9181 9205 wsmap="managed" 9182 9206 > … … 9325 9349 </desc> 9326 9350 </attribute> 9351 9352 <method name="getChildrenCount" const="yes"> 9353 <desc> 9354 Returns the number of direct childrens of this snapshot. 9355 </desc> 9356 <param name="childrenCount" type="unsigned long" dir="return"> 9357 <desc> 9358 </desc> 9359 </param> 9360 </method> 9327 9361 9328 9362 </interface> … … 10805 10839 medium which is being cloned. Even cloning to a child of the source 10806 10840 medium is possible. Note that when cloning to an existing image, the 10807 @a parent irgument is ignored.10841 @a parent argument is ignored. 10808 10842 10809 10843 After the returned progress object reports that the operation is -
trunk/src/VBox/Main/include/MachineImpl.h
r37380 r37449 529 529 STDMETHOD(AttachHostPciDevice(LONG hostAddress, LONG desiredGuestAddress, BOOL tryToUnbind)); 530 530 STDMETHOD(DetachHostPciDevice(LONG hostAddress)); 531 STDMETHOD(CloneTo(IMachine *aTarget, BOOL aFullClone, IProgress **aProgress));531 STDMETHOD(CloneTo(IMachine *aTarget, CloneMode_T mode, BOOL aFullClone, IProgress **aProgress)); 532 532 // public methods only for internal purposes 533 533 … … 841 841 842 842 struct CloneVMTask; 843 HRESULT cloneCreateMachineList(const ComPtr<ISnapshot> &pSnapshot, RTCList< ComPtr<IMachine> > &machineList) const; 844 settings::Snapshot cloneFindSnapshot(settings::MachineConfigFile *pMCF, const settings::SnapshotsList &snl, const Guid &id) const; 845 void cloneUpdateStorageLists(settings::StorageControllersList &sc, const Bstr &bstrOldId, const Bstr &bstrNewId) const; 846 void cloneUpdateSnapshotStorageLists(settings::SnapshotsList &sl, const Bstr &bstrOldId, const Bstr &bstrNewId) const; 847 843 848 static DECLCALLBACK(int) cloneVMThread(RTTHREAD Thread, void *pvUser); 844 849 HRESULT cloneVMTaskWorker(CloneVMTask *pTask); -
trunk/src/VBox/Main/include/SnapshotImpl.h
r36074 r37449 83 83 84 84 // ISnapshot methods 85 STDMETHOD(GetChildrenCount)(ULONG* count); 85 86 86 87 // public methods only for internal purposes -
trunk/src/VBox/Main/src-server/MachineImpl.cpp
r37412 r37449 6077 6077 ComObjPtr<Machine> pSrcMachine; 6078 6078 ComObjPtr<Machine> pTrgMachine; 6079 ComPtr<IMachine> pOldMachineState; 6079 6080 ComObjPtr<Progress> pProgress; 6080 bool fLink; 6081 Guid snapshotId; 6082 CloneMode_T mode; 6083 bool fLinkDisks; 6081 6084 typedef struct 6082 6085 { … … 6084 6087 uint64_t uSize; 6085 6088 }MediumTask; 6086 typedef RTCList<MediumTask> MediumTaskChain; 6089 typedef struct 6090 { 6091 RTCList<MediumTask> chain; 6092 bool fCreateDiffs; 6093 }MediumTaskChain; 6087 6094 RTCList<MediumTaskChain> llMedias; 6095 RTCList< std::pair<Utf8Str, Utf8Str> > llSaveStateFiles; /* Snapshot UUID -> File path */ 6088 6096 }; 6089 6097 6090 STDMETHODIMP Machine::CloneTo(IMachine *pTarget, BOOL fFullClone, IProgress **pProgress)6098 STDMETHODIMP Machine::CloneTo(IMachine *pTarget, CloneMode_T mode, BOOL fFullClone, IProgress **pProgress) 6091 6099 { 6092 6100 LogFlowFuncEnter(); … … 6106 6114 { 6107 6115 pTask = new CloneVMTask; 6108 pTask->pSrcMachine = this; 6109 pTask->pTrgMachine = static_cast<Machine*>(pTarget); 6110 pTask->fLink = !fFullClone; 6111 6116 pTask->pSrcMachine = this; 6117 pTask->pTrgMachine = static_cast<Machine*>(pTarget); 6118 pTask->fLinkDisks = !fFullClone; 6119 pTask->mode = mode; 6120 6121 /* Lock the target machine early (so nobody mess around with it in the meantime). */ 6112 6122 AutoWriteLock trgLock(pTask->pTrgMachine COMMA_LOCKVAL_SRC_POS); 6113 6123 6124 if (pTask->pSrcMachine->isSnapshotMachine()) 6125 pTask->snapshotId = static_cast<SnapshotMachine*>((Machine*)pTask->pSrcMachine)->getSnapshotId(); 6126 6127 /* Add the current machine and all snapshot machines below this machine 6128 * in a list for further processing. */ 6129 RTCList< ComPtr<IMachine> > machineList; 6130 6131 /* Include current state? */ 6132 if ( pTask->mode == CloneMode_MachineState 6133 || pTask->mode == CloneMode_AllStates) 6134 machineList.append(static_cast< ComPtr<IMachine> >(pTask->pSrcMachine)); 6135 /* Should be done a depth copy with all child snapshots? */ 6136 if ( pTask->mode == CloneMode_MachineAndChildStates 6137 || pTask->mode == CloneMode_AllStates) 6138 { 6139 ULONG cSnapshots = 0; 6140 rc = pTask->pSrcMachine->COMGETTER(SnapshotCount)(&cSnapshots); 6141 if (FAILED(rc)) throw rc; 6142 if (cSnapshots > 0) 6143 { 6144 Utf8Str id; 6145 if ( pTask->mode == CloneMode_MachineAndChildStates 6146 && !pTask->snapshotId.isEmpty()) 6147 id = pTask->snapshotId.toString(); 6148 ComPtr<ISnapshot> pSnapshot; 6149 rc = pTask->pSrcMachine->FindSnapshot(Bstr(id).raw(), pSnapshot.asOutParam()); 6150 if (FAILED(rc)) throw rc; 6151 rc = cloneCreateMachineList(pSnapshot, machineList); 6152 if (FAILED(rc)) throw rc; 6153 rc = pSnapshot->COMGETTER(Machine)(pTask->pOldMachineState.asOutParam()); 6154 if (FAILED(rc)) throw rc; 6155 } 6156 } 6157 6158 /* Go over every machine and walk over every attachment this machine has. */ 6114 6159 ULONG uCount = 2; /* One init task and the machine creation. */ 6115 6160 ULONG uTotalWeight = 2; /* The init task and the machine creation is worth one. */ 6116 for (MediaData::AttachmentList::iterator it = mMediaData->mAttachments.begin(); 6117 it != mMediaData->mAttachments.end(); 6118 ++it) 6119 { 6120 /* Query some info of the source image. */ 6121 const ComObjPtr<MediumAttachment> &pAtt = *it; 6122 DeviceType_T type; 6123 rc = pAtt->COMGETTER(Type)(&type); 6161 for (size_t i = 0; i < machineList.size(); ++i) 6162 { 6163 /* If this is the Snapshot Machine we want to clone, we need to 6164 * create a new diff file for the new "current state". */ 6165 bool fCreateDiffs = false; 6166 if (machineList.at(i) == pTask->pOldMachineState) 6167 fCreateDiffs = true; 6168 SafeIfaceArray<IMediumAttachment> sfaAttachments; 6169 rc = machineList.at(i)->COMGETTER(MediumAttachments)(ComSafeArrayAsOutParam(sfaAttachments)); 6124 6170 if (FAILED(rc)) throw rc; 6125 6126 /* Only harddisk's are of interest. */ 6127 if (type != DeviceType_HardDisk) 6128 continue; 6129 6130 /* Valid medium attached? */ 6131 ComPtr<IMedium> pSrcMedium; 6132 rc = pAtt->COMGETTER(Medium)(pSrcMedium.asOutParam()); 6133 if (FAILED(rc)) throw rc; 6134 if (pSrcMedium.isNull()) 6135 continue; 6136 6137 /* Build up a child->parent list of this attachment. (Note: we are 6138 * not interested of any child's not attached to this VM. So this 6139 * will not create a full copy of the base/child relationship.) */ 6140 Machine::CloneVMTask::MediumTaskChain mtc; 6141 while(!pSrcMedium.isNull()) 6171 /* Add all attachments (and there parents) of the different 6172 * machines to a worker list. */ 6173 for (size_t a = 0; a < sfaAttachments.size(); ++a) 6142 6174 { 6143 /* Refresh the state so that the file size get read. */6144 MediumState_Te;6145 rc = p SrcMedium->RefreshState(&e);6175 const ComPtr<IMediumAttachment> &pAtt = sfaAttachments[a]; 6176 DeviceType_T type; 6177 rc = pAtt->COMGETTER(Type)(&type); 6146 6178 if (FAILED(rc)) throw rc; 6147 LONG64 lSize; 6148 rc = pSrcMedium->COMGETTER(Size)(&lSize); 6179 6180 /* Only harddisk's are of interest. */ 6181 if (type != DeviceType_HardDisk) 6182 continue; 6183 6184 /* Valid medium attached? */ 6185 ComPtr<IMedium> pSrcMedium; 6186 rc = pAtt->COMGETTER(Medium)(pSrcMedium.asOutParam()); 6149 6187 if (FAILED(rc)) throw rc; 6150 6151 /* Save the current medium, for later cloning. */ 6152 Machine::CloneVMTask::MediumTask mt; 6153 mt.pMedium = pSrcMedium; 6154 mt.uSize = lSize; 6155 mtc.append(mt); 6156 6157 /* Calculate progress data */ 6158 ++uCount; 6159 uTotalWeight += lSize; 6160 6161 /* Query next parent. */ 6162 rc = pSrcMedium->COMGETTER(Parent)(pSrcMedium.asOutParam()); 6163 if (FAILED(rc)) throw rc; 6164 }; 6165 pTask->llMedias.append(mtc); 6188 if (pSrcMedium.isNull()) 6189 continue; 6190 6191 /* Build up a child->parent list of this attachment. (Note: we are 6192 * not interested of any child's not attached to this VM. So this 6193 * will not create a full copy of the base/child relationship.) */ 6194 Machine::CloneVMTask::MediumTaskChain mtc; 6195 mtc.fCreateDiffs = fCreateDiffs; 6196 while(!pSrcMedium.isNull()) 6197 { 6198 /* Refresh the state so that the file size get read. */ 6199 MediumState_T e; 6200 rc = pSrcMedium->RefreshState(&e); 6201 if (FAILED(rc)) throw rc; 6202 LONG64 lSize; 6203 rc = pSrcMedium->COMGETTER(Size)(&lSize); 6204 if (FAILED(rc)) throw rc; 6205 6206 /* Save the current medium, for later cloning. */ 6207 Machine::CloneVMTask::MediumTask mt; 6208 mt.pMedium = pSrcMedium; 6209 mt.uSize = lSize; 6210 mtc.chain.append(mt); 6211 6212 /* Calculate progress data */ 6213 ++uCount; 6214 uTotalWeight += lSize; 6215 6216 /* Query next parent. */ 6217 rc = pSrcMedium->COMGETTER(Parent)(pSrcMedium.asOutParam()); 6218 if (FAILED(rc)) throw rc; 6219 }; 6220 pTask->llMedias.append(mtc); 6221 } 6222 /* Todo: If this machine has save state files, they have to be copied as well. */ 6223 // Bstr bstrSrcSaveStatePath; 6224 // rc = machineList.at(i)->COMGETTER(StateFilePath)(bstrSrcSaveStatePath.asOutParam()); 6225 // if (FAILED(rc)) throw rc; 6226 // if (!bstrSrcSaveStatePath.isEmpty()) 6227 // pTask->llSaveStates.append(bstrSrcSaveStatePath); 6166 6228 } 6167 6229 … … 6231 6293 } 6232 6294 6295 HRESULT Machine::cloneCreateMachineList(const ComPtr<ISnapshot> &pSnapshot, RTCList< ComPtr<IMachine> > &machineList) const 6296 { 6297 HRESULT rc = S_OK; 6298 Bstr name; 6299 rc = pSnapshot->COMGETTER(Name)(name.asOutParam()); 6300 if (FAILED(rc)) return rc; 6301 6302 ComPtr<IMachine> pMachine; 6303 rc = pSnapshot->COMGETTER(Machine)(pMachine.asOutParam()); 6304 if (FAILED(rc)) return rc; 6305 machineList.append(pMachine); 6306 6307 SafeIfaceArray<ISnapshot> sfaChilds; 6308 rc = pSnapshot->COMGETTER(Children)(ComSafeArrayAsOutParam(sfaChilds)); 6309 if (FAILED(rc)) return rc; 6310 for (size_t i = 0; i < sfaChilds.size(); ++i) 6311 { 6312 rc = cloneCreateMachineList(sfaChilds[i], machineList); 6313 if (FAILED(rc)) return rc; 6314 } 6315 6316 return rc; 6317 } 6318 6319 settings::Snapshot Machine::cloneFindSnapshot(settings::MachineConfigFile *pMCF, const settings::SnapshotsList &snl, const Guid &id) const 6320 { 6321 settings::SnapshotsList::const_iterator it; 6322 for (it = snl.begin(); it != snl.end(); ++it) 6323 { 6324 if (it->uuid == id) 6325 return *it; 6326 else if (!it->llChildSnapshots.empty()) 6327 return cloneFindSnapshot(pMCF, it->llChildSnapshots, id); 6328 } 6329 return settings::Snapshot(); 6330 } 6331 6332 void Machine::cloneUpdateStorageLists(settings::StorageControllersList &sc, const Bstr &bstrOldId, const Bstr &bstrNewId) const 6333 { 6334 settings::StorageControllersList::iterator it3; 6335 for (it3 = sc.begin(); 6336 it3 != sc.end(); 6337 ++it3) 6338 { 6339 settings::AttachedDevicesList &llAttachments = it3->llAttachedDevices; 6340 settings::AttachedDevicesList::iterator it4; 6341 for (it4 = llAttachments.begin(); 6342 it4 != llAttachments.end(); 6343 ++it4) 6344 { 6345 if ( it4->deviceType == DeviceType_HardDisk 6346 && it4->uuid == bstrOldId) 6347 { 6348 it4->uuid = bstrNewId; 6349 } 6350 } 6351 } 6352 } 6353 6354 void Machine::cloneUpdateSnapshotStorageLists(settings::SnapshotsList &sl, const Bstr &bstrOldId, const Bstr &bstrNewId) const 6355 { 6356 settings::SnapshotsList::iterator it; 6357 for ( it = sl.begin(); 6358 it != sl.end(); 6359 ++it) 6360 { 6361 cloneUpdateStorageLists(it->storage.llStorageControllers, bstrOldId, bstrNewId); 6362 if (!it->llChildSnapshots.empty()) 6363 cloneUpdateSnapshotStorageLists(it->llChildSnapshots, bstrOldId, bstrNewId); 6364 } 6365 } 6366 6233 6367 /** 6234 6368 * Task thread implementation for Machine::CloneTo(), called from Machine::cloneVMThread(). … … 6271 6405 /* Reset media registry. */ 6272 6406 pTrgMCF->mediaRegistry.llHardDisks.clear(); 6273 /* Reset all snapshots. */ 6274 pTrgMCF->llFirstSnapshot.clear(); 6275 pTrgMCF->uuidCurrentSnapshot.clear(); 6407 /* If we got a valid snapshot id, replace the hardware/storage section 6408 * with the stuff from the snapshot. */ 6409 settings::Snapshot sn; 6410 if (!pTask->snapshotId.isEmpty()) 6411 sn = cloneFindSnapshot(pTrgMCF, pTrgMCF->llFirstSnapshot, pTask->snapshotId); 6412 6413 if (pTask->mode == CloneMode_MachineState) 6414 { 6415 if (!sn.uuid.isEmpty()) 6416 { 6417 pTrgMCF->hardwareMachine = sn.hardware; 6418 pTrgMCF->storageMachine = sn.storage; 6419 } 6420 6421 /* Remove any hint on snapshots. */ 6422 pTrgMCF->llFirstSnapshot.clear(); 6423 pTrgMCF->uuidCurrentSnapshot.clear(); 6424 }else 6425 if ( pTask->mode == CloneMode_MachineAndChildStates 6426 && !sn.uuid.isEmpty()) 6427 { 6428 /* Copy the snapshot data to the current machine. */ 6429 pTrgMCF->hardwareMachine = sn.hardware; 6430 pTrgMCF->storageMachine = sn.storage; 6431 6432 /* The snapshot will be the root one. */ 6433 pTrgMCF->uuidCurrentSnapshot = sn.uuid; 6434 pTrgMCF->llFirstSnapshot.clear(); 6435 pTrgMCF->llFirstSnapshot.push_back(sn); 6436 } 6437 6438 /* Reset the snapshot folder to 'Snapshots' within the target directory. 6439 * Todo: Not sure if this is what we want. */ 6440 pTrgMCF->machineUserData.strSnapshotFolder = "Snapshots"; 6276 6441 pTrgMCF->strStateFile = ""; 6277 6442 /* Force writing of setting file. */ … … 6281 6446 pTrgMCF->uuid = pTask->pTrgMachine->mData->mUuid; 6282 6447 6448 /* The absolute name of the snapshot folder. */ 6449 Utf8Str strTrgSnapshotFolder = Utf8StrFmt("%s%c%s%c", strTrgMachineFolder.c_str(), RTPATH_DELIMITER, pTrgMCF->machineUserData.strSnapshotFolder.c_str(), RTPATH_DELIMITER); 6450 6451 /* We need to create a map with the already created medias. This is 6452 * necessary, cause different snapshots could have the same 6453 * parents/parent chain. If a medium is in this map already, it isn't 6454 * cloned a second time, but simply used. */ 6455 typedef std::map<Utf8Str, ComObjPtr<Medium> > TStrMediumMap; 6456 typedef std::pair<Utf8Str, ComObjPtr<Medium> > TStrMediumPair; 6457 TStrMediumMap map; 6283 6458 for (size_t i = 0; i < pTask->llMedias.size(); ++i) 6284 6459 { 6285 6460 const Machine::CloneVMTask::MediumTaskChain &mtc = pTask->llMedias.at(i); 6286 6461 ComObjPtr<Medium> pNewParent; 6287 for (size_t a = mtc. size(); a > 0; --a)6462 for (size_t a = mtc.chain.size(); a > 0; --a) 6288 6463 { 6289 const Machine::CloneVMTask::MediumTask &mt = mtc. at(a - 1);6464 const Machine::CloneVMTask::MediumTask &mt = mtc.chain.at(a - 1); 6290 6465 ComPtr<IMedium> pMedium = mt.pMedium; 6291 6466 … … 6297 6472 if (FAILED(rc)) throw rc; 6298 6473 6299 ComPtr<IMediumFormat> pSrcFormat; 6300 rc = pMedium->COMGETTER(MediumFormat)(pSrcFormat.asOutParam()); 6301 ULONG uSrcCaps = 0; 6302 rc = pSrcFormat->COMGETTER(Capabilities)(&uSrcCaps); 6474 Bstr bstrSrcId; 6475 rc = pMedium->COMGETTER(Id)(bstrSrcId.asOutParam()); 6303 6476 if (FAILED(rc)) throw rc; 6304 6477 6305 Bstr bstrSrcFormat = "VDI"; 6306 ULONG srcVar = MediumVariant_Standard; 6307 /* Is the source file based? */ 6308 if ((uSrcCaps & MediumFormatCapabilities_File) == MediumFormatCapabilities_File) 6478 /* Is a clone already there? */ 6479 TStrMediumMap::iterator it = map.find(Utf8Str(bstrSrcId)); 6480 if (it != map.end()) 6481 pNewParent = it->second; 6482 else 6309 6483 { 6310 /* Yes, just use the source format. Otherwise the defaults 6311 * will be used. */ 6312 rc = pMedium->COMGETTER(Format)(bstrSrcFormat.asOutParam()); 6484 ComPtr<IMediumFormat> pSrcFormat; 6485 rc = pMedium->COMGETTER(MediumFormat)(pSrcFormat.asOutParam()); 6486 ULONG uSrcCaps = 0; 6487 rc = pSrcFormat->COMGETTER(Capabilities)(&uSrcCaps); 6313 6488 if (FAILED(rc)) throw rc; 6314 rc = pMedium->COMGETTER(Variant)(&srcVar); 6489 6490 Bstr bstrSrcFormat = "VDI"; 6491 ULONG srcVar = MediumVariant_Standard; 6492 /* Is the source file based? */ 6493 if ((uSrcCaps & MediumFormatCapabilities_File) == MediumFormatCapabilities_File) 6494 { 6495 /* Yes, just use the source format. Otherwise the defaults 6496 * will be used. */ 6497 rc = pMedium->COMGETTER(Format)(bstrSrcFormat.asOutParam()); 6498 if (FAILED(rc)) throw rc; 6499 rc = pMedium->COMGETTER(Variant)(&srcVar); 6500 if (FAILED(rc)) throw rc; 6501 } 6502 6503 /* Start creating the clone. */ 6504 ComObjPtr<Medium> pTarget; 6505 rc = pTarget.createObject(); 6315 6506 if (FAILED(rc)) throw rc; 6507 6508 Utf8Str strFile = Utf8StrFmt("%s%c%lS", strTrgMachineFolder.c_str(), RTPATH_DELIMITER, bstrSrcName.raw()); 6509 rc = pTarget->init(mParent, 6510 Utf8Str(bstrSrcFormat), 6511 strFile, 6512 pTask->pTrgMachine->mData->mUuid, /* media registry */ 6513 NULL /* llRegistriesThatNeedSaving */); 6514 if (FAILED(rc)) throw rc; 6515 6516 /* Do the disk cloning. */ 6517 ComPtr<IProgress> progress2; 6518 rc = pMedium->CloneTo(pTarget, 6519 srcVar, 6520 pNewParent, 6521 progress2.asOutParam()); 6522 if (FAILED(rc)) throw rc; 6523 6524 /* Wait until the asynchrony process has finished. */ 6525 srcLock.release(); 6526 rc = pTask->pProgress->WaitForAsyncProgressCompletion(progress2); 6527 srcLock.acquire(); 6528 if (FAILED(rc)) throw rc; 6529 6530 /* Check the result of the asynchrony process. */ 6531 LONG iRc; 6532 rc = progress2->COMGETTER(ResultCode)(&iRc); 6533 if (FAILED(rc)) throw rc; 6534 if (FAILED(iRc)) 6535 { 6536 /* If the thread of the progress object has an error, then 6537 * retrieve the error info from there, or it'll be lost. */ 6538 ProgressErrorInfo info(progress2); 6539 throw setError(iRc, Utf8Str(info.getText()).c_str()); 6540 } 6541 6542 map.insert(TStrMediumPair(Utf8Str(bstrSrcId), pTarget)); 6543 6544 /* Remember created medias. */ 6545 newMedias.append(pTarget); 6546 /* This medium becomes the parent of the next medium in the 6547 * chain. */ 6548 pNewParent = pTarget; 6316 6549 } 6317 6318 /* Start creating the clone. */ 6319 ComObjPtr<Medium> pTarget; 6320 rc = pTarget.createObject(); 6550 } 6551 6552 /* Create diffs for the last image chain. */ 6553 if (mtc.fCreateDiffs) 6554 { 6555 Bstr bstrSrcId; 6556 rc = pNewParent->COMGETTER(Id)(bstrSrcId.asOutParam()); 6321 6557 if (FAILED(rc)) throw rc; 6322 6323 Utf8Str strFile = Utf8StrFmt("%s%c%lS", strTrgMachineFolder.c_str(), RTPATH_DELIMITER, bstrSrcName.raw()); 6324 rc = pTarget->init(mParent, 6325 Utf8Str(bstrSrcFormat), 6326 strFile, 6327 pTask->pTrgMachine->mData->mUuid, /* media registry */ 6328 NULL /* llRegistriesThatNeedSaving */); 6558 GuidList *pllRegistriesThatNeedSaving; 6559 ComObjPtr<Medium> diff; 6560 diff.createObject(); 6561 rc = diff->init(mParent, 6562 pNewParent->getPreferredDiffFormat(), 6563 strTrgSnapshotFolder, 6564 pTask->pTrgMachine->mData->mUuid, 6565 NULL); // pllRegistriesThatNeedSaving 6329 6566 if (FAILED(rc)) throw rc; 6330 6331 /* Do the disk cloning. */ 6332 ComPtr<IProgress> progress2; 6333 rc = pMedium->CloneTo(pTarget, 6334 srcVar, 6335 pNewParent, 6336 progress2.asOutParam()); 6567 MediumLockList *pMediumLockList(new MediumLockList()); /* todo: deleteeeeeeeee */ 6568 rc = diff->createMediumLockList(true /* fFailIfInaccessible */, 6569 true /* fMediumLockWrite */, 6570 pNewParent, 6571 *pMediumLockList); 6337 6572 if (FAILED(rc)) throw rc; 6338 6339 /* Wait until the asynchrony process has finished. */ 6340 srcLock.release(); 6341 rc = pTask->pProgress->WaitForAsyncProgressCompletion(progress2); 6342 srcLock.acquire(); 6573 rc = pMediumLockList->Lock(); 6343 6574 if (FAILED(rc)) throw rc; 6344 6345 /* Check the result of the asynchrony process. */ 6346 LONG iRc; 6347 rc = progress2->COMGETTER(ResultCode)(&iRc); 6575 rc = pNewParent->createDiffStorage(diff, MediumVariant_Standard, 6576 pMediumLockList, 6577 NULL /* aProgress */, 6578 true /* aWait */, 6579 NULL); // pllRegistriesThatNeedSaving 6580 delete pMediumLockList; 6348 6581 if (FAILED(rc)) throw rc; 6349 if (FAILED(iRc)) 6350 { 6351 /* If the thread of the progress object has an error, then 6352 * retrieve the error info from there, or it'll be lost. */ 6353 ProgressErrorInfo info(progress2); 6354 throw setError(iRc, Utf8Str(info.getText()).c_str()); 6355 } 6356 /* Remember created medias. */ 6357 newMedias.append(pTarget); 6358 /* This medium becomes the parent of the next medium in the 6359 * chain. */ 6360 pNewParent = pTarget; 6582 pNewParent = diff; 6361 6583 } 6362 6363 6584 Bstr bstrSrcId; 6364 rc = mtc. first().pMedium->COMGETTER(Id)(bstrSrcId.asOutParam());6585 rc = mtc.chain.first().pMedium->COMGETTER(Id)(bstrSrcId.asOutParam()); 6365 6586 if (FAILED(rc)) throw rc; 6366 6587 Bstr bstrTrgId; … … 6369 6590 /* We have to patch the configuration, so it contains the new 6370 6591 * medium uuid instead of the old one. */ 6371 settings::StorageControllersList::iterator it3; 6372 for (it3 = pTrgMCF->storageMachine.llStorageControllers.begin(); 6373 it3 != pTrgMCF->storageMachine.llStorageControllers.end(); 6374 ++it3) 6592 cloneUpdateStorageLists(pTrgMCF->storageMachine.llStorageControllers, bstrSrcId, bstrTrgId); 6593 cloneUpdateSnapshotStorageLists(pTrgMCF->llFirstSnapshot, bstrSrcId, bstrTrgId); 6594 } 6595 /* Todo: Clone all save state files. */ 6596 // for (size_t i = 0; i < pTask->llSaveStates.size(); ++i) 6597 // { 6598 // RTPrintf("save state: %s\n", pTask->llSaveStates.at(i).c_str()); 6599 // RTFileCopy(llSaveStates.at(i).c_str(),); 6600 // } 6601 6602 if (false) 6603 // if (!pTask->pOldMachineState.isNull()) 6604 { 6605 SafeIfaceArray<IMediumAttachment> sfaAttachments; 6606 rc = pTask->pOldMachineState->COMGETTER(MediumAttachments)(ComSafeArrayAsOutParam(sfaAttachments)); 6607 if (FAILED(rc)) throw rc; 6608 for (size_t a = 0; a < sfaAttachments.size(); ++a) 6375 6609 { 6376 settings::AttachedDevicesList &llAttachments = it3->llAttachedDevices; 6377 settings::AttachedDevicesList::iterator it4; 6378 for (it4 = llAttachments.begin(); 6379 it4 != llAttachments.end(); 6380 ++it4) 6381 { 6382 if ( it4->deviceType == DeviceType_HardDisk 6383 && it4->uuid == bstrSrcId) 6384 it4->uuid = bstrTrgId; 6385 } 6610 const ComPtr<IMediumAttachment> &pAtt = sfaAttachments[a]; 6611 DeviceType_T type; 6612 rc = pAtt->COMGETTER(Type)(&type); 6613 if (FAILED(rc)) throw rc; 6614 6615 /* Only harddisk's are of interest. */ 6616 if (type != DeviceType_HardDisk) 6617 continue; 6618 6619 /* Valid medium attached? */ 6620 ComPtr<IMedium> pSrcMedium; 6621 rc = pAtt->COMGETTER(Medium)(pSrcMedium.asOutParam()); 6622 if (FAILED(rc)) throw rc; 6623 if (pSrcMedium.isNull()) 6624 continue; 6625 6626 // ComObjPtr<Medium> pMedium = static_cast<Medium*>((IMedium*)pSrcMedium); 6627 // ComObjPtr<Medium> diff; 6628 // diff.createObject(); 6629 // store this diff in the same registry as the parent 6630 // Guid uuidRegistryParent; 6631 // if (!medium->getFirstRegistryMachineId(uuidRegistryParent)) 6632 // { 6633 // parent image has no registry: this can happen if we're attaching a new immutable 6634 // image that has not yet been attached (medium then points to the base and we're 6635 // creating the diff image for the immutable, and the parent is not yet registered); 6636 // put the parent in the machine registry then 6637 // addMediumToRegistry(medium, llRegistriesThatNeedSaving, &uuidRegistryParent); 6638 // } 6639 // rc = diff->init(mParent, 6640 // pMedium->getPreferredDiffFormat(), 6641 // strFullSnapshotFolder.append(RTPATH_SLASH_STR), 6642 // uuidRegistryParent, 6643 // pllRegistriesThatNeedSaving); 6644 // if (FAILED(rc)) throw rc; 6645 // 6646 // rc = pMedium->createDiffStorage(diff, MediumVariant_Standard, 6647 // pMediumLockList, 6648 // NULL /* aProgress */, 6649 // true /* aWait */, 6650 // pllRegistriesThatNeedSaving); 6386 6651 } 6387 6652 } -
trunk/src/VBox/Main/src-server/SnapshotImpl.cpp
r37380 r37449 446 446 SafeIfaceArray<ISnapshot> collection(m->llChildren); 447 447 collection.detachTo(ComSafeArrayOutArg(aChildren)); 448 449 return S_OK; 450 } 451 452 STDMETHODIMP Snapshot::GetChildrenCount(ULONG* count) 453 { 454 CheckComArgOutPointerValid(count); 455 456 *count = getChildrenCount(); 448 457 449 458 return S_OK;
Note:
See TracChangeset
for help on using the changeset viewer.