Changeset 44395 in vbox for trunk/src/VBox/Main/src-server/MediumImpl.cpp
- Timestamp:
- Jan 26, 2013 7:52:47 PM (12 years ago)
- svn:sync-xref-src-repo-rev:
- 83369
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/src-server/MediumImpl.cpp
r44381 r44395 4519 4519 else 4520 4520 return setStateError(); 4521 } 4522 4523 /** 4524 * Queries the preferred merge direction from this to the other medium, i.e. 4525 * the one which requires the least amount of I/O and therefore time and 4526 * disk consumption. 4527 * 4528 * @returns Status code. 4529 * @retval E_FAIL in case determining the merge direction fails for some reason, 4530 * for example if getting the size of the media fails. There is no 4531 * error set though and the caller is free to continue to find out 4532 * what was going wrong later. Leaves fMergeForward unset. 4533 * @retval VBOX_E_INVALID_OBJECT_STATE if both media are not related to each other 4534 * An error is set. 4535 * @param pOther The other medium to merge with. 4536 * @param fMergeForward Resulting preferred merge direction (out). 4537 */ 4538 HRESULT Medium::queryPreferredMergeDirection(const ComObjPtr<Medium> &pOther, 4539 bool &fMergeForward) 4540 { 4541 AssertReturn(pOther != NULL, E_FAIL); 4542 AssertReturn(pOther != this, E_FAIL); 4543 4544 AutoCaller autoCaller(this); 4545 AssertComRCReturnRC(autoCaller.rc()); 4546 4547 AutoCaller otherCaller(pOther); 4548 AssertComRCReturnRC(otherCaller.rc()); 4549 4550 HRESULT rc = S_OK; 4551 bool fThisParent = false; /**<< Flag whether this medium is the parent of pOther. */ 4552 4553 try 4554 { 4555 // locking: we need the tree lock first because we access parent pointers 4556 AutoWriteLock treeLock(m->pVirtualBox->getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS); 4557 4558 /* more sanity checking and figuring out the current merge direction */ 4559 ComObjPtr<Medium> pMedium = getParent(); 4560 while (!pMedium.isNull() && pMedium != pOther) 4561 pMedium = pMedium->getParent(); 4562 if (pMedium == pOther) 4563 fThisParent = false; 4564 else 4565 { 4566 pMedium = pOther->getParent(); 4567 while (!pMedium.isNull() && pMedium != this) 4568 pMedium = pMedium->getParent(); 4569 if (pMedium == this) 4570 fThisParent = true; 4571 else 4572 { 4573 Utf8Str tgtLoc; 4574 { 4575 AutoReadLock alock(pOther COMMA_LOCKVAL_SRC_POS); 4576 tgtLoc = pOther->getLocationFull(); 4577 } 4578 4579 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 4580 throw setError(VBOX_E_INVALID_OBJECT_STATE, 4581 tr("Media '%s' and '%s' are unrelated"), 4582 m->strLocationFull.c_str(), tgtLoc.c_str()); 4583 } 4584 } 4585 4586 /* 4587 * Figure out the preferred merge direction. The current way is to 4588 * get the current sizes of file based images and select the merge 4589 * direction depending on the size. 4590 * 4591 * Can't use the VD API to get current size here as the media might 4592 * be write locked by a running VM. Resort to RTFileQuerySize(). 4593 */ 4594 int vrc = VINF_SUCCESS; 4595 uint64_t cbMediumThis = 0; 4596 uint64_t cbMediumOther = 0; 4597 4598 if (isMediumFormatFile() && pOther->isMediumFormatFile()) 4599 { 4600 vrc = RTFileQuerySize(this->getLocationFull().c_str(), &cbMediumThis); 4601 if (RT_SUCCESS(vrc)) 4602 { 4603 vrc = RTFileQuerySize(pOther->getLocationFull().c_str(), 4604 &cbMediumOther); 4605 } 4606 4607 if (RT_FAILURE(vrc)) 4608 rc = E_FAIL; 4609 else 4610 { 4611 /* 4612 * Check which merge direction might be more optimal. 4613 * This method is not bullet proof of course as there might 4614 * be overlapping blocks in the images so the file size is 4615 * not the best indicator but it is good enough for our purpose 4616 * and everything else is too complicated, especially when the 4617 * media are used by a running VM. 4618 */ 4619 bool fMergeIntoThis = cbMediumThis > cbMediumOther; 4620 fMergeForward = fMergeIntoThis ^ fThisParent; 4621 } 4622 } 4623 } 4624 catch (HRESULT aRC) { rc = aRC; } 4625 4626 return rc; 4521 4627 } 4522 4628
Note:
See TracChangeset
for help on using the changeset viewer.