Changeset 27779 in vbox for trunk/src/VBox/Main/ApplianceImpl.cpp
- Timestamp:
- Mar 29, 2010 11:28:45 AM (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/ApplianceImpl.cpp
r27730 r27779 69 69 struct Appliance::Data 70 70 { 71 enum ApplianceState { ApplianceIdle, ApplianceImporting, ApplianceExporting }; 72 71 73 Data() 72 : pReader(NULL) {} 74 : state(ApplianceIdle), 75 pReader(NULL) 76 { 77 } 73 78 74 79 ~Data() … … 81 86 } 82 87 83 LocationInfo locInfo; /* The location info for the currently processed OVF */ 84 85 OVFReader *pReader; 86 87 list< ComObjPtr<VirtualSystemDescription> > virtualSystemDescriptions; 88 89 list<Utf8Str> llWarnings; 90 91 ULONG ulWeightPerOperation; 92 Utf8Str strOVFSHA1Digest; 88 ApplianceState state; 89 90 LocationInfo locInfo; // location info for the currently processed OVF 91 92 OVFReader *pReader; 93 94 bool fBusyWriting; // state protection; while this is true nobody else can call methods 95 96 list< ComObjPtr<VirtualSystemDescription> > 97 virtualSystemDescriptions; 98 99 list<Utf8Str> llWarnings; 100 101 ULONG ulWeightPerOperation; 102 Utf8Str strOVFSHA1Digest; 93 103 }; 94 104 … … 371 381 //////////////////////////////////////////////////////////////////////////////// 372 382 383 /** 384 * Returns true if the appliance is in "idle" state. This should always be the 385 * case unless an import or export is currently in progress. Similar to machine 386 * states, this permits the Appliance implementation code to let go of the 387 * Appliance object lock while a time-consuming disk conversion is in progress 388 * without exposing the appliance to conflicting calls. 389 * 390 * This sets an error on "this" (the appliance) and returns false if the appliance 391 * is busy. The caller should then return E_ACCESSDENIED. 392 * 393 * Must be called from under the object lock! 394 * 395 * @return 396 */ 397 bool Appliance::isApplianceIdle() const 398 { 399 if (m->state == Data::ApplianceImporting) 400 setError(VBOX_E_INVALID_OBJECT_STATE, "The appliance is busy importing files"); 401 else if (m->state == Data::ApplianceExporting) 402 setError(VBOX_E_INVALID_OBJECT_STATE, "The appliance is busy exporting files"); 403 else 404 return true; 405 406 return false; 407 } 408 373 409 HRESULT Appliance::searchUniqueVMName(Utf8Str& aName) const 374 410 { … … 885 921 HRESULT rc = S_OK; 886 922 887 switch (task->taskType)923 switch (task->taskType) 888 924 { 889 925 case TaskImportOVF::Read: … … 1103 1139 1104 1140 AutoWriteLock appLock(this COMMA_LOCKVAL_SRC_POS); 1141 1142 if (!isApplianceIdle()) 1143 return VERR_ACCESS_DENIED; 1144 1145 // Change the appliance state so we can safely leave the lock while doing time-consuming 1146 // disk imports; also the below method calls do all kinds of locking which conflicts with 1147 // the appliance object lock 1148 m->state = Data::ApplianceImporting; 1149 appLock.release(); 1105 1150 1106 1151 HRESULT rc = S_OK; … … 1906 1951 } 1907 1952 1953 // restore the appliance state 1954 appLock.acquire(); 1955 m->state = Data::ApplianceIdle; 1956 1908 1957 pTask->rc = rc; 1909 1958 … … 2257 2306 if (FAILED(autoCaller.rc())) return autoCaller.rc(); 2258 2307 2259 AutoWriteLock appLock(this COMMA_LOCKVAL_SRC_POS);2260 2261 2308 HRESULT rc = S_OK; 2262 2309 2263 2310 try 2264 2311 { 2312 AutoMultiWriteLock2 multiLock(&mVirtualBox->getMediaTreeLockHandle(), this->lockHandle() COMMA_LOCKVAL_SRC_POS); 2313 2265 2314 xml::Document doc; 2266 2315 xml::ElementNode *pelmRoot = doc.createRootElement("Envelope"); … … 2935 2984 } 2936 2985 2937 // finally, fill in the network section we set up empty above according2986 // now, fill in the network section we set up empty above according 2938 2987 // to the networks we found with the hardware items 2939 2988 map<Utf8Str, bool>::const_iterator itN; … … 2948 2997 } 2949 2998 2999 // Finally, write out the disks! 3000 3001 // This can take a very long time so leave the locks; in particular, we have the media tree 3002 // lock which Medium::CloneTo() will request, and that would deadlock. Instead, protect 3003 // the appliance by resetting its state so we can safely leave the lock 3004 m->state = Data::ApplianceExporting; 3005 multiLock.release(); 3006 2950 3007 list<Utf8Str> diskList; 2951 3008 map<Utf8Str, const VirtualSystemDescriptionEntry*>::const_iterator itS; … … 3003 3060 if (!pTask->progress.isNull()) 3004 3061 pTask->progress->SetNextOperation(BstrFmt(tr("Exporting virtual disk image '%s'"), strSrcFilePath.c_str()), 3005 pDiskEntry->ulSizeMB); // operation's weight, as set up with the IProgress originally);3062 pDiskEntry->ulSizeMB); // operation's weight, as set up with the IProgress originally); 3006 3063 3007 3064 // now wait for the background disk operation to complete; this throws HRESULTs on error … … 3079 3136 rc = aRC; 3080 3137 } 3138 3139 AutoWriteLock appLock(this COMMA_LOCKVAL_SRC_POS); 3140 // reset the state so others can call methods again 3141 m->state = Data::ApplianceIdle; 3081 3142 3082 3143 pTask->rc = rc; … … 3278 3339 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 3279 3340 3341 if (!isApplianceIdle()) 3342 return E_ACCESSDENIED; 3343 3280 3344 Bstr bstrPath(m->locInfo.strPath); 3281 3345 bstrPath.cloneTo(aPath); … … 3297 3361 3298 3362 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 3363 3364 if (!isApplianceIdle()) 3365 return E_ACCESSDENIED; 3299 3366 3300 3367 if (m->pReader) // OVFReader instantiated? … … 3356 3423 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 3357 3424 3425 if (!isApplianceIdle()) 3426 return E_ACCESSDENIED; 3427 3358 3428 SafeIfaceArray<IVirtualSystemDescription> sfaVSD(m->virtualSystemDescriptions); 3359 3429 sfaVSD.detachTo(ComSafeArrayOutArg(aVirtualSystemDescriptions)); … … 3377 3447 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 3378 3448 3449 if (!isApplianceIdle()) 3450 return E_ACCESSDENIED; 3451 3379 3452 if (m->pReader) 3380 3453 { … … 3422 3495 3423 3496 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 3497 3498 if (!isApplianceIdle()) 3499 return E_ACCESSDENIED; 3424 3500 3425 3501 HRESULT rc = S_OK; … … 3439 3515 return setError(E_FAIL, 3440 3516 tr("Cannot interpret appliance without reading it first (call read() before interpret())")); 3517 3518 // Change the appliance state so we can safely leave the lock while doing time-consuming 3519 // disk imports; also the below method calls do all kinds of locking which conflicts with 3520 // the appliance object lock 3521 m->state = Data::ApplianceImporting; 3522 alock.release(); 3441 3523 3442 3524 /* Try/catch so we can clean up on error */ … … 3853 3935 } 3854 3936 3937 // reset the appliance state 3938 alock.acquire(); 3939 m->state = Data::ApplianceIdle; 3940 3855 3941 return rc; 3856 3942 } … … 3870 3956 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 3871 3957 3958 if (!isApplianceIdle()) 3959 return E_ACCESSDENIED; 3960 3872 3961 if (!m->pReader) 3873 3962 return setError(E_FAIL, … … 3900 3989 3901 3990 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 3991 3992 if (!isApplianceIdle()) 3993 return E_ACCESSDENIED; 3902 3994 3903 3995 ComObjPtr<VFSExplorer> explorer; … … 3934 4026 3935 4027 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 4028 4029 if (!isApplianceIdle()) 4030 return E_ACCESSDENIED; 3936 4031 3937 4032 // see if we can handle this file; for now we insist it has an ".ovf" extension … … 3984 4079 3985 4080 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 4081 4082 if (!isApplianceIdle()) 4083 return E_ACCESSDENIED; 3986 4084 3987 4085 com::SafeArray<BSTR> sfaWarnings(m->llWarnings.size()); … … 4406 4504 if (FAILED(autoCaller.rc())) return autoCaller.rc(); 4407 4505 4408 AutoReadLock alock1(this COMMA_LOCKVAL_SRC_POS);4409 4410 4506 ComObjPtr<VirtualSystemDescription> pNewDesc; 4411 4507 … … 4423 4519 ComPtr<IUSBController> pUsbController; 4424 4520 ComPtr<IAudioAdapter> pAudioAdapter; 4521 4522 // first, call the COM methods, as they request locks 4523 rc = COMGETTER(USBController)(pUsbController.asOutParam()); 4524 if (FAILED(rc)) 4525 fUSBEnabled = false; 4526 else 4527 rc = pUsbController->COMGETTER(Enabled)(&fUSBEnabled); 4528 4529 // request the machine lock while acessing internal members 4530 AutoReadLock alock1(this COMMA_LOCKVAL_SRC_POS); 4531 4532 pAudioAdapter = mAudioAdapter; 4533 rc = pAudioAdapter->COMGETTER(Enabled)(&fAudioEnabled); 4534 if (FAILED(rc)) throw rc; 4535 rc = pAudioAdapter->COMGETTER(AudioController)(&audioController); 4536 if (FAILED(rc)) throw rc; 4425 4537 4426 4538 // get name … … 4443 4555 // snapshotFolder? 4444 4556 // VRDPServer? 4445 4446 // this is more tricky so use the COM method4447 rc = COMGETTER(USBController)(pUsbController.asOutParam());4448 if (FAILED(rc))4449 fUSBEnabled = false;4450 else4451 rc = pUsbController->COMGETTER(Enabled)(&fUSBEnabled);4452 4453 pAudioAdapter = mAudioAdapter;4454 rc = pAudioAdapter->COMGETTER(Enabled)(&fAudioEnabled);4455 if (FAILED(rc)) throw rc;4456 rc = pAudioAdapter->COMGETTER(AudioController)(&audioController);4457 if (FAILED(rc)) throw rc;4458 4557 4459 4558 // create a new virtual system
Note:
See TracChangeset
for help on using the changeset viewer.