Changeset 15556 in vbox for trunk/src/VBox/Main
- Timestamp:
- Dec 15, 2008 10:31:49 PM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/HardDisk2Impl.cpp
r15486 r15556 57 57 struct HardDisk2::Task : public com::SupportErrorInfoBase 58 58 { 59 enum Operation { CreateDynamic, CreateFixed, CreateDiff, Merge, Delete }; 59 enum Operation { CreateDynamic, CreateFixed, CreateDiff, 60 Merge, Clone, Delete }; 60 61 61 62 HardDisk2 *that; … … 1128 1129 IProgress **aProgress) 1129 1130 { 1130 if (aProgress == NULL) 1131 return E_POINTER; 1131 CheckComArgOutPointerValid (aProgress); 1132 1132 1133 1133 AutoCaller autoCaller (this); … … 1184 1184 IProgress **aProgress) 1185 1185 { 1186 if (aProgress == NULL) 1187 return E_POINTER; 1186 CheckComArgOutPointerValid (aProgress); 1188 1187 1189 1188 AutoCaller autoCaller (this); … … 1239 1238 STDMETHODIMP HardDisk2::DeleteStorage (IProgress **aProgress) 1240 1239 { 1241 if (aProgress == NULL) 1242 return E_POINTER; 1240 CheckComArgOutPointerValid (aProgress); 1241 1242 AutoCaller autoCaller (this); 1243 CheckComRCReturnRC (autoCaller.rc()); 1243 1244 1244 1245 ComObjPtr <Progress> progress; … … 1256 1257 STDMETHODIMP HardDisk2::CreateDiffStorage (IHardDisk2 *aTarget, IProgress **aProgress) 1257 1258 { 1258 if (aTarget == NULL) 1259 return E_INVALIDARG; 1260 if (aProgress == NULL) 1261 return E_POINTER; 1259 CheckComArgNotNull (aTarget); 1260 CheckComArgOutPointerValid (aProgress); 1262 1261 1263 1262 AutoCaller autoCaller (this); … … 1306 1305 STDMETHODIMP HardDisk2::CloneTo (IHardDisk2 *aTarget, IProgress **aProgress) 1307 1306 { 1307 CheckComArgNotNull (aTarget); 1308 CheckComArgOutPointerValid (aProgress); 1309 1308 1310 AutoCaller autoCaller (this); 1309 1311 CheckComRCReturnRC (autoCaller.rc()); 1310 1312 1311 ReturnComNotImplemented(); 1313 ComObjPtr <HardDisk2> target; 1314 HRESULT rc = mVirtualBox->cast (aTarget, target); 1315 CheckComRCReturnRC (rc); 1316 1317 AutoMultiWriteLock2 alock (this, target); 1318 1319 /* We want to be locked for reading as long as the clone hard disk is being 1320 * created*/ 1321 rc = LockRead (NULL); 1322 CheckComRCReturnRC (rc); 1323 1324 ComObjPtr <Progress> progress; 1325 1326 try 1327 { 1328 if (target->m.state != MediaState_NotCreated) 1329 throw target->setStateError(); 1330 1331 progress.createObject(); 1332 rc = progress->init (mVirtualBox, static_cast <IHardDisk2 *> (this), 1333 BstrFmt (tr ("Creating a clone hard disk '%s'"), 1334 target->name().raw()), 1335 FALSE /* aCancelable */); 1336 CheckComRCThrowRC (rc); 1337 1338 /* setup task object and thread to carry out the operation 1339 * asynchronously */ 1340 1341 std::auto_ptr <Task> task (new Task (this, progress, Task::Clone)); 1342 AssertComRCThrowRC (task->autoCaller.rc()); 1343 1344 task->setData (target); 1345 1346 rc = task->startThread(); 1347 CheckComRCThrowRC (rc); 1348 1349 /* go to Creating state before leaving the lock */ 1350 target->m.state = MediaState_Creating; 1351 1352 /* task is now owned (or already deleted) by taskThread() so release it */ 1353 task.release(); 1354 } 1355 catch (HRESULT aRC) 1356 { 1357 rc = aRC; 1358 } 1359 1360 if (FAILED (rc)) 1361 { 1362 HRESULT rc2 = UnlockRead (NULL); 1363 AssertComRC (rc2); 1364 /* Note: on success, taskThread() will unlock this */ 1365 } 1366 else 1367 { 1368 /* return progress to the caller */ 1369 progress.queryInterfaceTo (aProgress); 1370 } 1371 1372 return rc; 1312 1373 } 1313 1374 … … 3203 3264 uint64_t size = 0, logicalSize = 0; 3204 3265 3205 /* the object may request a specific UUID (through a special3206 * form of the setLocation() argumet)*/3266 /* The object may request a specific UUID (through a special form of 3267 * the setLocation() argumet). Otherwise we have to generate it */ 3207 3268 Guid id = that->m.id; 3269 bool generateUuid = id.isEmpty(); 3270 if (generateUuid) 3271 { 3272 id.create(); 3273 /* VirtualBox::registerHardDisk2() will need UUID */ 3274 unconst (that->m.id) = id; 3275 } 3208 3276 3209 3277 try … … 3238 3306 task->d.size * _1M, 3239 3307 VD_IMAGE_FLAGS_NONE, 3240 NULL, &geo, &geo, 3241 id.isEmpty() ? NULL : id.raw(), 3308 NULL, &geo, &geo, id.raw(), 3242 3309 VD_OPEN_FLAGS_NORMAL, 3243 3310 NULL, that->mm.vdDiskIfaces); … … 3251 3318 } 3252 3319 3253 if (capabilities & HardDiskFormatCapabilities_Uuid)3254 {3255 RTUUID uuid;3256 vrc = VDGetUuid (hdd, 0, &uuid);3257 ComAssertRCThrow (vrc, E_FAIL);3258 3259 if (!id.isEmpty())3260 Assert (id == uuid);3261 else3262 id = uuid;3263 }3264 else3265 {3266 /* we have to generate an UUID ourselves */3267 id.create();3268 }3269 3270 3320 size = VDGetFileSize (hdd, 0); 3271 3321 logicalSize = VDGetSize (hdd, 0) / _1M; … … 3279 3329 if (SUCCEEDED (rc)) 3280 3330 { 3281 /* mVirtualBox->registerHardDisk2() needs a write lock */3282 AutoWriteLock vboxLock (that->mVirtualBox);3283 thatLock.enter();3284 3285 unconst (that->m.id) = id;3286 3287 that->m.size = size;3288 that->mm.logicalSize = logicalSize;3289 3290 3331 /* register with mVirtualBox as the last step and move to 3291 3332 * Created state only on success (leaving an orphan file is 3292 3333 * better than breaking media registry consistency) */ 3293 3334 rc = that->mVirtualBox->registerHardDisk2 (that); 3294 3295 if (SUCCEEDED (rc))3296 that->m.state = MediaState_Created;3297 3335 } 3298 3336 3299 if (FAILED (rc)) 3337 thatLock.maybeEnter(); 3338 3339 if (SUCCEEDED (rc)) 3300 3340 { 3301 thatLock.maybeEnter(); 3302 3341 that->m.state = MediaState_Created; 3342 3343 that->m.size = size; 3344 that->mm.logicalSize = logicalSize; 3345 } 3346 else 3347 { 3303 3348 /* back to NotCreated on failiure */ 3304 3349 that->m.state = MediaState_NotCreated; 3350 3351 /* reset UUID to prevent it from being reused next time */ 3352 if (generateUuid) 3353 unconst (that->m.id).clear(); 3305 3354 } 3306 3355 … … 3320 3369 3321 3370 uint64_t size = 0, logicalSize = 0; 3371 3372 /* The object may request a specific UUID (through a special form of 3373 * the setLocation() argumet). Otherwise we have to generate it */ 3374 Guid targetId = target->m.id; 3375 bool generateUuid = targetId.isEmpty(); 3376 if (generateUuid) 3377 { 3378 targetId.create(); 3379 /* VirtualBox::registerHardDisk2() will need UUID */ 3380 unconst (target->m.id) = targetId; 3381 } 3322 3382 3323 3383 try … … 3332 3392 Utf8Str targetFormat (target->mm.format); 3333 3393 Utf8Str targetLocation (target->m.locationFull); 3334 Guid targetId = target->m.id;3335 3336 /* UUID must have been set by setLocation() */3337 Assert (!targetId.isEmpty());3338 3394 3339 3395 Assert (target->m.state == MediaState_Creating); … … 3434 3490 /* back to NotCreated on failiure */ 3435 3491 target->m.state = MediaState_NotCreated; 3492 3493 /* reset UUID to prevent it from being reused next time */ 3494 if (generateUuid) 3495 unconst (target->m.id).clear(); 3436 3496 } 3437 3497 … … 3759 3819 //////////////////////////////////////////////////////////////////////// 3760 3820 3821 case Task::Clone: 3822 { 3823 ComObjPtr <HardDisk2> &target = task->d.target; 3824 3825 /* Lock both in {parent,child} order. The lock is also used as a 3826 * signal from the task initiator (which releases it only after 3827 * RTThreadCreate()) that we can start the job*/ 3828 AutoMultiWriteLock2 thatLock (that, target); 3829 3830 uint64_t size = 0, logicalSize = 0; 3831 3832 /* The object may request a specific UUID (through a special form of 3833 * the setLocation() argumet). Otherwise we have to generate it */ 3834 Guid targetId = target->m.id; 3835 bool generateUuid = targetId.isEmpty(); 3836 if (generateUuid) 3837 { 3838 targetId.create(); 3839 /* VirtualBox::registerHardDisk2() will need UUID */ 3840 unconst (target->m.id) = targetId; 3841 } 3842 3843 try 3844 { 3845 PVBOXHDD hdd; 3846 int vrc = VDCreate (that->mm.vdDiskIfaces, &hdd); 3847 ComAssertRCThrow (vrc, E_FAIL); 3848 3849 Utf8Str format (that->mm.format); 3850 Utf8Str location (that->m.locationFull); 3851 3852 Utf8Str targetFormat (target->mm.format); 3853 Utf8Str targetLocation (target->m.locationFull); 3854 3855 Assert (target->m.state == MediaState_Creating); 3856 3857 Assert (that->m.state == MediaState_LockedRead); 3858 3859 /* unlock before the potentially lengthy operation */ 3860 thatLock.leave(); 3861 3862 try 3863 { 3864 vrc = VDOpen (hdd, format, location, 3865 VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO, 3866 NULL); 3867 if (RT_FAILURE (vrc)) 3868 { 3869 throw setError (E_FAIL, 3870 tr ("Could not open the hard disk storage " 3871 "unit '%s'%s"), 3872 location.raw(), that->vdError (vrc).raw()); 3873 } 3874 3875 /* ensure the target directory exists */ 3876 rc = VirtualBox::ensureFilePathExists (targetLocation); 3877 CheckComRCThrowRC (rc); 3878 3879 /* needed for vdProgressCallback */ 3880 that->mm.vdProgress = task->progress; 3881 3882 PVBOXHDD targetHdd; 3883 int vrc = VDCreate (that->mm.vdDiskIfaces, &targetHdd); 3884 ComAssertRCThrow (vrc, E_FAIL); 3885 3886 vrc = VDCopy (hdd, 0, targetHdd, targetFormat, 3887 targetLocation, false, 0, targetId.raw(), 3888 NULL, NULL, that->mm.vdDiskIfaces); 3889 3890 that->mm.vdProgress = NULL; 3891 3892 if (RT_FAILURE (vrc)) 3893 { 3894 VDDestroy (targetHdd); 3895 3896 throw setError (E_FAIL, 3897 tr ("Could not create the clone hard disk " 3898 "'%s'%s"), 3899 targetLocation.raw(), that->vdError (vrc).raw()); 3900 } 3901 3902 size = VDGetFileSize (hdd, 0); 3903 logicalSize = VDGetSize (hdd, 0) / _1M; 3904 3905 VDDestroy (targetHdd); 3906 } 3907 catch (HRESULT aRC) { rc = aRC; } 3908 3909 VDDestroy (hdd); 3910 } 3911 catch (HRESULT aRC) { rc = aRC; } 3912 3913 if (SUCCEEDED (rc)) 3914 { 3915 /* we set mParent & children() (note that thatLock is released 3916 * here), but lock VirtualBox first to follow the rule */ 3917 AutoMultiWriteLock2 alock (that->mVirtualBox->lockHandle(), 3918 that->treeLock()); 3919 3920 Assert (target->mParent.isNull()); 3921 3922 if (!that->mParent.isNull()) 3923 { 3924 /* associate the clone with the original's parent and 3925 * deassociate from VirtualBox */ 3926 target->mParent = that->mParent; 3927 that->mParent->addDependentChild (target); 3928 target->mVirtualBox->removeDependentChild (target); 3929 3930 /* register with mVirtualBox as the last step and move to 3931 * Created state only on success (leaving an orphan file is 3932 * better than breaking media registry consistency) */ 3933 rc = that->mVirtualBox->registerHardDisk2 (target); 3934 3935 if (FAILED (rc)) 3936 { 3937 /* break the parent association on failure to register */ 3938 target->mVirtualBox->addDependentChild (target); 3939 that->mParent->removeDependentChild (target); 3940 target->mParent.setNull(); 3941 } 3942 } 3943 else 3944 { 3945 /* just register */ 3946 rc = that->mVirtualBox->registerHardDisk2 (target); 3947 } 3948 } 3949 3950 thatLock.maybeEnter(); 3951 3952 if (SUCCEEDED (rc)) 3953 { 3954 target->m.state = MediaState_Created; 3955 3956 target->m.size = size; 3957 target->mm.logicalSize = logicalSize; 3958 } 3959 else 3960 { 3961 /* back to NotCreated on failiure */ 3962 target->m.state = MediaState_NotCreated; 3963 3964 /* reset UUID to prevent it from being reused next time */ 3965 if (generateUuid) 3966 unconst (target->m.id).clear(); 3967 } 3968 3969 if (isAsync) 3970 { 3971 /* unlock ourselves when done (unless in MediaState_LockedWrite 3972 * state because of taking the online snapshot*/ 3973 if (that->m.state != MediaState_LockedWrite) 3974 { 3975 HRESULT rc2 = that->UnlockRead (NULL); 3976 AssertComRC (rc2); 3977 } 3978 } 3979 3980 /* Note that in sync mode, it's the caller's responsibility to 3981 * unlock the hard disk */ 3982 3983 break; 3984 } 3985 3986 //////////////////////////////////////////////////////////////////////// 3987 3761 3988 case Task::Delete: 3762 3989 {
Note:
See TracChangeset
for help on using the changeset viewer.