Changeset 32695 in vbox
- Timestamp:
- Sep 22, 2010 11:16:48 AM (14 years ago)
- Location:
- trunk/src/VBox/Main
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/MediumImpl.cpp
r32691 r32695 561 561 }; 562 562 563 class Medium::ExportTask : public Medium::Task 564 { 565 public: 566 ExportTask(Medium *aMedium, 567 Progress *aProgress, 568 const char *aFilename, 569 MediumFormat *aFormat, 570 MediumVariant_T aVariant, 571 void *aVDImageIOCallbacks, 572 void *aVDImageIOUser, 573 MediumLockList *aSourceMediumLockList, 574 bool fKeepSourceMediumLockList = false) 575 : Medium::Task(aMedium, aProgress), 576 mpSourceMediumLockList(aSourceMediumLockList), 577 mFilename(aFilename), 578 mFormat(aFormat), 579 mVariant(aVariant), 580 mfKeepSourceMediumLockList(fKeepSourceMediumLockList) 581 { 582 AssertReturnVoidStmt(aSourceMediumLockList != NULL, mRC = E_FAIL); 583 584 mVDImageIfaces = aMedium->m->vdImageIfaces; 585 if (aVDImageIOCallbacks) 586 { 587 int vrc = VDInterfaceAdd(&mVDInterfaceIO, "Medium::vdInterfaceIO", 588 VDINTERFACETYPE_IO, aVDImageIOCallbacks, 589 aVDImageIOUser, &mVDImageIfaces); 590 AssertRCReturnVoidStmt(vrc, mRC = E_FAIL); 591 } 592 } 593 594 ~ExportTask() 595 { 596 if (!mfKeepSourceMediumLockList && mpSourceMediumLockList) 597 delete mpSourceMediumLockList; 598 } 599 600 MediumLockList *mpSourceMediumLockList; 601 Utf8Str mFilename; 602 ComObjPtr<MediumFormat> mFormat; 603 MediumVariant_T mVariant; 604 PVDINTERFACE mVDImageIfaces; 605 606 private: 607 virtual HRESULT handler(); 608 609 bool mfKeepSourceMediumLockList; 610 VDINTERFACE mVDInterfaceIO; 611 }; 612 563 613 /** 564 614 * Thread function for time-consuming medium tasks. … … 684 734 { 685 735 return mMedium->taskMergeHandler(*this); 736 } 737 738 /** 739 * Implementation code for the "export" task. 740 */ 741 HRESULT Medium::ExportTask::handler() 742 { 743 return mMedium->taskExportHandler(*this); 686 744 } 687 745 … … 5054 5112 } 5055 5113 5114 5115 HRESULT Medium::exportFile(const char *aFilename, 5116 ComObjPtr<MediumFormat> aFormat, 5117 MediumVariant_T aVariant, 5118 void *aVDImageIOCallbacks, void *aVDImageIOUser, 5119 ComObjPtr<Progress> aProgress) 5120 { 5121 return E_FAIL; 5122 5123 AssertPtrReturn(aFilename, E_INVALIDARG); 5124 AssertReturn(!aFormat.isNull(), E_INVALIDARG); 5125 AssertReturn(!aProgress.isNull(), E_INVALIDARG); 5126 5127 AutoCaller autoCaller(this); 5128 if (FAILED(autoCaller.rc())) return autoCaller.rc(); 5129 5130 HRESULT rc = S_OK; 5131 Medium::Task *pTask = NULL; 5132 5133 try 5134 { 5135 // locking: we need the tree lock first because we access parent pointers 5136 AutoReadLock treeLock(m->pVirtualBox->getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS); 5137 // and we need to write-lock the media involved 5138 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 5139 5140 /* Build the source lock list. */ 5141 MediumLockList *pSourceMediumLockList(new MediumLockList()); 5142 rc = createMediumLockList(true /* fFailIfInaccessible */, 5143 false /* fMediumLockWrite */, 5144 NULL, 5145 *pSourceMediumLockList); 5146 if (FAILED(rc)) 5147 { 5148 delete pSourceMediumLockList; 5149 throw rc; 5150 } 5151 5152 rc = pSourceMediumLockList->Lock(); 5153 if (FAILED(rc)) 5154 { 5155 delete pSourceMediumLockList; 5156 throw setError(rc, 5157 tr("Failed to lock source media '%s'"), 5158 getLocationFull().c_str()); 5159 } 5160 5161 /* setup task object to carry out the operation asynchronously */ 5162 pTask = new Medium::ExportTask(this, aProgress, aFilename, aFormat, 5163 aVariant, aVDImageIOCallbacks, 5164 aVDImageIOUser, pSourceMediumLockList); 5165 rc = pTask->rc(); 5166 AssertComRC(rc); 5167 if (FAILED(rc)) 5168 throw rc; 5169 } 5170 catch (HRESULT aRC) { rc = aRC; } 5171 5172 if (SUCCEEDED(rc)) 5173 rc = startThread(pTask); 5174 else if (pTask != NULL) 5175 delete pTask; 5176 5177 return rc; 5178 } 5179 5056 5180 //////////////////////////////////////////////////////////////////////////////// 5057 5181 // … … 6846 6970 } 6847 6971 6972 /** 6973 * Implementation code for the "export" task. 6974 * 6975 * This only gets started from Medium::exportFile() and always runs 6976 * asynchronously. It doesn't touch anything configuration related, so 6977 * we never save the VirtualBox.xml file here. 6978 * 6979 * @param task 6980 * @return 6981 */ 6982 HRESULT Medium::taskExportHandler(Medium::ExportTask &task) 6983 { 6984 HRESULT rc = S_OK; 6985 6986 try 6987 { 6988 /* Lock all in {parent,child} order. The lock is also used as a 6989 * signal from the task initiator (which releases it only after 6990 * RTThreadCreate()) that we can start the job. */ 6991 AutoWriteLock thisLock(this COMMA_LOCKVAL_SRC_POS); 6992 6993 PVBOXHDD hdd; 6994 int vrc = VDCreate(m->vdDiskIfaces, &hdd); 6995 ComAssertRCThrow(vrc, E_FAIL); 6996 6997 try 6998 { 6999 /* Open all media in the source chain. */ 7000 MediumLockList::Base::const_iterator sourceListBegin = 7001 task.mpSourceMediumLockList->GetBegin(); 7002 MediumLockList::Base::const_iterator sourceListEnd = 7003 task.mpSourceMediumLockList->GetEnd(); 7004 for (MediumLockList::Base::const_iterator it = sourceListBegin; 7005 it != sourceListEnd; 7006 ++it) 7007 { 7008 const MediumLock &mediumLock = *it; 7009 const ComObjPtr<Medium> &pMedium = mediumLock.GetMedium(); 7010 AutoReadLock alock(pMedium COMMA_LOCKVAL_SRC_POS); 7011 7012 /* sanity check */ 7013 Assert(pMedium->m->state == MediumState_LockedRead); 7014 7015 /** Open all media in read-only mode. */ 7016 vrc = VDOpen(hdd, 7017 pMedium->m->strFormat.c_str(), 7018 pMedium->m->strLocationFull.c_str(), 7019 VD_OPEN_FLAGS_READONLY, 7020 pMedium->m->vdImageIfaces); 7021 if (RT_FAILURE(vrc)) 7022 throw setError(VBOX_E_FILE_ERROR, 7023 tr("Could not open the medium storage unit '%s'%s"), 7024 pMedium->m->strLocationFull.c_str(), 7025 vdError(vrc).c_str()); 7026 } 7027 7028 Utf8Str targetFormat(task.mFormat->getId()); 7029 Utf8Str targetLocation(task.mFilename); 7030 7031 Assert(m->state == MediumState_LockedRead); 7032 7033 /* unlock before the potentially lengthy operation */ 7034 thisLock.release(); 7035 7036 /* ensure the target directory exists */ 7037 rc = VirtualBox::ensureFilePathExists(targetLocation); 7038 if (FAILED(rc)) 7039 throw rc; 7040 7041 PVBOXHDD targetHdd; 7042 vrc = VDCreate(m->vdDiskIfaces, &targetHdd); 7043 ComAssertRCThrow(vrc, E_FAIL); 7044 7045 try 7046 { 7047 vrc = VDCopy(hdd, 7048 VD_LAST_IMAGE, 7049 targetHdd, 7050 targetFormat.c_str(), 7051 targetLocation.c_str(), 7052 false /* fMoveByRename */, 7053 0 /* cbSize */, 7054 task.mVariant, 7055 NULL /* pDstUuid */, 7056 NULL /* pVDIfsOperation */, 7057 task.mVDImageIfaces, 7058 task.mVDOperationIfaces); 7059 if (RT_FAILURE(vrc)) 7060 throw setError(VBOX_E_FILE_ERROR, 7061 tr("Could not create the clone medium '%s'%s"), 7062 targetLocation.c_str(), vdError(vrc).c_str()); 7063 } 7064 catch (HRESULT aRC) { rc = aRC; } 7065 7066 VDDestroy(targetHdd); 7067 } 7068 catch (HRESULT aRC) { rc = aRC; } 7069 7070 VDDestroy(hdd); 7071 } 7072 catch (HRESULT aRC) { rc = aRC; } 7073 7074 /* Everything is explicitly unlocked when the task exits, 7075 * as the task destruction also destroys the source chain. */ 7076 7077 /* Make sure the source chain is released early, otherwise it can 7078 * lead to deadlocks with concurrent IAppliance activities. */ 7079 task.mpSourceMediumLockList->Clear(); 7080 7081 return rc; 7082 } 7083 6848 7084 /* vi: set tabstop=4 shiftwidth=4 expandtab: */ -
trunk/src/VBox/Main/include/MediumImpl.h
r31777 r32695 243 243 HRESULT fixParentUuidOfChildren(const MediaList &childrenToReparent); 244 244 245 /** 246 * Used by IAppliance to export disk images. 247 * 248 * @param aFilename Filename to create (UTF8). 249 * @param aFormat Which medium format to use. 250 * @param aVariant Which exact image format variant to use. 251 * @param aVDImageIOCallbacks Pointer to the callback table for a 252 * VDINTERFACEIO interface. May be NULL. 253 * @param aVDImageIOUser Opaque data for the callbacks. 254 * @param aProgress Progress object to use. 255 * @return 256 */ 257 HRESULT exportFile(const char *aFilename, 258 ComObjPtr<MediumFormat> aFormat, 259 MediumVariant_T aVariant, 260 void *aVDImageIOCallbacks, void *aVDImageIOUser, 261 ComObjPtr<Progress> aProgress); 262 245 263 /** Returns a preferred format for a differencing hard disk. */ 246 264 Utf8Str getPreferredDiffFormat(); … … 293 311 class DeleteTask; 294 312 class MergeTask; 313 class ExportTask; 295 314 friend class Task; 296 315 friend class CreateBaseTask; … … 302 321 friend class DeleteTask; 303 322 friend class MergeTask; 323 friend class ExportTask; 304 324 305 325 HRESULT startThread(Medium::Task *pTask); … … 314 334 HRESULT taskCompactHandler(Medium::CompactTask &task); 315 335 HRESULT taskResizeHandler(Medium::ResizeTask &task); 336 HRESULT taskExportHandler(Medium::ExportTask &task); 316 337 317 338 struct Data; // opaque data struct, defined in MediumImpl.cpp
Note:
See TracChangeset
for help on using the changeset viewer.