Changeset 25888 in vbox for trunk/src/VBox/Main
- Timestamp:
- Jan 18, 2010 12:16:07 PM (15 years ago)
- svn:sync-xref-src-repo-rev:
- 56697
- Location:
- trunk/src/VBox/Main
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/MediumImpl.cpp
r25887 r25888 5641 5641 } 5642 5642 5643 /** 5644 * Implementation code called from Medium::taskThread for the "delete" task. 5645 * @return 5646 */ 5647 HRESULT Medium::taskThreadDelete() 5648 { 5649 HRESULT rc = S_OK; 5650 5651 /* The lock is also used as a signal from the task initiator (which 5652 * releases it only after RTThreadCreate()) that we can start the job */ 5653 AutoWriteLock thisLock(this COMMA_LOCKVAL_SRC_POS); 5654 5655 try 5656 { 5657 PVBOXHDD hdd; 5658 int vrc = VDCreate(m->vdDiskIfaces, &hdd); 5659 ComAssertRCThrow(vrc, E_FAIL); 5660 5661 Utf8Str format(m->strFormat); 5662 Utf8Str location(m->strLocationFull); 5663 5664 /* unlock before the potentially lengthy operation */ 5665 Assert(m->state == MediumState_Deleting); 5666 thisLock.leave(); 5667 5668 try 5669 { 5670 vrc = VDOpen(hdd, 5671 format.c_str(), 5672 location.c_str(), 5673 VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO, 5674 m->vdDiskIfaces); 5675 if (RT_SUCCESS(vrc)) 5676 vrc = VDClose(hdd, true /* fDelete */); 5677 5678 if (RT_FAILURE(vrc)) 5679 throw setError(E_FAIL, 5680 tr("Could not delete the hard disk storage unit '%s'%s"), 5681 location.raw(), vdError(vrc).raw()); 5682 5683 } 5684 catch (HRESULT aRC) { rc = aRC; } 5685 5686 VDDestroy(hdd); 5687 } 5688 catch (HRESULT aRC) { rc = aRC; } 5689 5690 thisLock.maybeEnter(); 5691 5692 /* go to the NotCreated state even on failure since the storage 5693 * may have been already partially deleted and cannot be used any 5694 * more. One will be able to manually re-open the storage if really 5695 * needed to re-register it. */ 5696 m->state = MediumState_NotCreated; 5697 5698 /* Reset UUID to prevent Create* from reusing it again */ 5699 unconst(m->id).clear(); 5700 5701 return rc; 5702 } 5703 5704 /** 5705 * Implementation code called from Medium::taskThread for the "reset" task. 5706 * @param task 5707 * @param pvdOperationIfaces 5708 * @return 5709 */ 5710 HRESULT Medium::taskThreadReset(void *pvdOperationIfaces, bool fIsAsync) 5711 { 5712 HRESULT rc = S_OK; 5713 5714 PVDINTERFACE vdOperationIfaces = (PVDINTERFACE)pvdOperationIfaces; 5715 5716 /* The lock is also used as a signal from the task initiator (which 5717 * releases it only after RTThreadCreate()) that we can start the job */ 5718 AutoWriteLock thisLock(this COMMA_LOCKVAL_SRC_POS); 5719 5720 /// @todo Below we use a pair of delete/create operations to reset 5721 /// the diff contents but the most efficient way will of course be 5722 /// to add a VDResetDiff() API call 5723 5724 uint64_t size = 0, logicalSize = 0; 5725 5726 try 5727 { 5728 PVBOXHDD hdd; 5729 int vrc = VDCreate(m->vdDiskIfaces, &hdd); 5730 ComAssertRCThrow(vrc, E_FAIL); 5731 5732 Guid id = m->id; 5733 Utf8Str format(m->strFormat); 5734 Utf8Str location(m->strLocationFull); 5735 5736 Medium *pParent = m->pParent; 5737 Guid parentId = pParent->m->id; 5738 Utf8Str parentFormat(pParent->m->strFormat); 5739 Utf8Str parentLocation(pParent->m->strLocationFull); 5740 5741 Assert(m->state == MediumState_LockedWrite); 5742 5743 /* unlock before the potentially lengthy operation */ 5744 thisLock.leave(); 5745 5746 try 5747 { 5748 /* first, delete the storage unit */ 5749 vrc = VDOpen(hdd, format.c_str(), location.c_str(), 5750 VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO, 5751 m->vdDiskIfaces); 5752 if (RT_SUCCESS(vrc)) 5753 vrc = VDClose(hdd, true /* fDelete */); 5754 5755 if (RT_FAILURE(vrc)) 5756 { 5757 throw setError(E_FAIL, 5758 tr("Could not delete the hard disk storage unit '%s'%s"), 5759 location.raw(), vdError(vrc).raw()); 5760 } 5761 5762 /* next, create it again */ 5763 vrc = VDOpen(hdd, parentFormat.c_str(), parentLocation.c_str(), 5764 VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO, 5765 m->vdDiskIfaces); 5766 if (RT_FAILURE(vrc)) 5767 { 5768 throw setError(E_FAIL, 5769 tr("Could not open the hard disk storage unit '%s'%s"), 5770 parentLocation.raw(), vdError(vrc).raw()); 5771 } 5772 5773 vrc = VDCreateDiff(hdd, format.c_str(), location.c_str(), 5774 /// @todo use the same image variant as before 5775 VD_IMAGE_FLAGS_NONE, 5776 NULL, id.raw(), 5777 parentId.raw(), 5778 VD_OPEN_FLAGS_NORMAL, 5779 m->vdDiskIfaces, 5780 vdOperationIfaces); 5781 if (RT_FAILURE(vrc)) 5782 { 5783 throw setError(E_FAIL, 5784 tr("Could not create the differencing hard disk storage unit '%s'%s"), 5785 location.raw(), vdError(vrc).raw()); 5786 } 5787 5788 size = VDGetFileSize(hdd, 1); 5789 logicalSize = VDGetSize(hdd, 1) / _1M; 5790 } 5791 catch (HRESULT aRC) { rc = aRC; } 5792 5793 VDDestroy(hdd); 5794 } 5795 catch (HRESULT aRC) { rc = aRC; } 5796 5797 thisLock.enter(); 5798 5799 m->size = size; 5800 m->logicalSize = logicalSize; 5801 5802 if (fIsAsync) 5803 { 5804 /* unlock ourselves when done */ 5805 HRESULT rc2 = UnlockWrite(NULL); 5806 AssertComRC(rc2); 5807 } 5808 5809 /* Note that in sync mode, it's the caller's responsibility to 5810 * unlock the hard disk */ 5811 5812 return rc; 5813 } 5814 5815 /** 5816 * Implementation code called from Medium::taskThread for the "compact" task. 5817 * @param pvdOperationIfaces 5818 * @return 5819 */ 5820 HRESULT Medium::taskThreadCompact(Task &task, void *pvdOperationIfaces) 5821 { 5822 HRESULT rc = S_OK; 5823 5824 PVDINTERFACE vdOperationIfaces = (PVDINTERFACE)pvdOperationIfaces; 5825 5826 /* Lock all in {parent,child} order. The lock is also used as a 5827 * signal from the task initiator (which releases it only after 5828 * RTThreadCreate()) that we can start the job. */ 5829 AutoWriteLock thisLock(this COMMA_LOCKVAL_SRC_POS); 5830 5831 ImageChain *imgChain = task.d.images.get(); 5832 5833 try 5834 { 5835 PVBOXHDD hdd; 5836 int vrc = VDCreate(m->vdDiskIfaces, &hdd); 5837 ComAssertRCThrow(vrc, E_FAIL); 5838 5839 try 5840 { 5841 /* Open all hard disk images in the chain. */ 5842 MediaList::const_iterator last = imgChain->end(); 5843 last--; 5844 for (MediaList::const_iterator it = imgChain->begin(); 5845 it != imgChain->end(); 5846 ++it) 5847 { 5848 /* sanity check */ 5849 if (it == last) 5850 Assert((*it)->m->state == MediumState_LockedWrite); 5851 else 5852 Assert((*it)->m->state == MediumState_LockedRead); 5853 5854 /** Open all images but last in read-only mode. */ 5855 vrc = VDOpen(hdd, 5856 (*it)->m->strFormat.c_str(), 5857 (*it)->m->strLocationFull.c_str(), 5858 (it == last) ? VD_OPEN_FLAGS_NORMAL : VD_OPEN_FLAGS_READONLY, 5859 (*it)->m->vdDiskIfaces); 5860 if (RT_FAILURE(vrc)) 5861 throw setError(E_FAIL, 5862 tr("Could not open the hard disk storage unit '%s'%s"), 5863 (*it)->m->strLocationFull.raw(), 5864 vdError(vrc).raw()); 5865 } 5866 5867 Assert(m->state == MediumState_LockedWrite); 5868 5869 Utf8Str location(m->strLocationFull); 5870 5871 /* unlock before the potentially lengthy operation */ 5872 thisLock.leave(); 5873 5874 vrc = VDCompact(hdd, VD_LAST_IMAGE, vdOperationIfaces); 5875 if (RT_FAILURE(vrc)) 5876 { 5877 if (vrc == VERR_NOT_SUPPORTED) 5878 throw setError(VBOX_E_NOT_SUPPORTED, 5879 tr("Compacting is not yet supported for hard disk '%s'"), 5880 location.raw()); 5881 else if (vrc == VERR_NOT_IMPLEMENTED) 5882 throw setError(E_NOTIMPL, 5883 tr("Compacting is not implemented, hard disk '%s'"), 5884 location.raw()); 5885 else 5886 throw setError(E_FAIL, 5887 tr("Could not compact hard disk '%s'%s"), 5888 location.raw(), 5889 vdError(vrc).raw()); 5890 } 5891 } 5892 catch (HRESULT aRC) { rc = aRC; } 5893 5894 VDDestroy(hdd); 5895 } 5896 catch (HRESULT aRC) { rc = aRC; } 5897 5898 /* Everything is explicitly unlocked when the task exits, 5899 * as the task destruction also destroys the image chain. */ 5900 5901 return rc; 5902 } 5903 5643 5904 5644 5905 /** … … 5676 5937 AssertRCReturn(vrc1, E_FAIL); 5677 5938 5678 /// @todo ugly hack, fix ComAssert... later5679 #define setError that->setError5680 5681 5939 /* Note: no need in AutoCaller because Task does that */ 5682 5940 … … 5707 5965 5708 5966 case Task::Delete: 5709 { 5710 /* The lock is also used as a signal from the task initiator (which 5711 * releases it only after RTThreadCreate()) that we can start the job */ 5712 AutoWriteLock thatLock(that COMMA_LOCKVAL_SRC_POS); 5713 5714 try 5715 { 5716 PVBOXHDD hdd; 5717 int vrc = VDCreate(that->m->vdDiskIfaces, &hdd); 5718 ComAssertRCThrow(vrc, E_FAIL); 5719 5720 Utf8Str format(that->m->strFormat); 5721 Utf8Str location(that->m->strLocationFull); 5722 5723 /* unlock before the potentially lengthy operation */ 5724 Assert(that->m->state == MediumState_Deleting); 5725 thatLock.leave(); 5726 5727 try 5728 { 5729 vrc = VDOpen(hdd, format.c_str(), location.c_str(), 5730 VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO, 5731 that->m->vdDiskIfaces); 5732 if (RT_SUCCESS(vrc)) 5733 vrc = VDClose(hdd, true /* fDelete */); 5734 5735 if (RT_FAILURE(vrc)) 5736 { 5737 throw setError(E_FAIL, 5738 tr("Could not delete the hard disk storage unit '%s'%s"), 5739 location.raw(), that->vdError(vrc).raw()); 5740 } 5741 5742 } 5743 catch (HRESULT aRC) { rc = aRC; } 5744 5745 VDDestroy(hdd); 5746 } 5747 catch (HRESULT aRC) { rc = aRC; } 5748 5749 thatLock.maybeEnter(); 5750 5751 /* go to the NotCreated state even on failure since the storage 5752 * may have been already partially deleted and cannot be used any 5753 * more. One will be able to manually re-open the storage if really 5754 * needed to re-register it. */ 5755 that->m->state = MediumState_NotCreated; 5756 5757 /* Reset UUID to prevent Create* from reusing it again */ 5758 unconst(that->m->id).clear(); 5759 5760 break; 5761 } 5967 rc = that->taskThreadDelete(); 5968 break; 5762 5969 5763 5970 case Task::Reset: 5764 { 5765 /* The lock is also used as a signal from the task initiator (which 5766 * releases it only after RTThreadCreate()) that we can start the job */ 5767 AutoWriteLock thatLock(that COMMA_LOCKVAL_SRC_POS); 5768 5769 /// @todo Below we use a pair of delete/create operations to reset 5770 /// the diff contents but the most efficient way will of course be 5771 /// to add a VDResetDiff() API call 5772 5773 uint64_t size = 0, logicalSize = 0; 5774 5775 try 5776 { 5777 PVBOXHDD hdd; 5778 int vrc = VDCreate(that->m->vdDiskIfaces, &hdd); 5779 ComAssertRCThrow(vrc, E_FAIL); 5780 5781 Guid id = that->m->id; 5782 Utf8Str format(that->m->strFormat); 5783 Utf8Str location(that->m->strLocationFull); 5784 5785 Medium *pParent = that->m->pParent; 5786 Guid parentId = pParent->m->id; 5787 Utf8Str parentFormat(pParent->m->strFormat); 5788 Utf8Str parentLocation(pParent->m->strLocationFull); 5789 5790 Assert(that->m->state == MediumState_LockedWrite); 5791 5792 /* unlock before the potentially lengthy operation */ 5793 thatLock.leave(); 5794 5795 try 5796 { 5797 /* first, delete the storage unit */ 5798 vrc = VDOpen(hdd, format.c_str(), location.c_str(), 5799 VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO, 5800 that->m->vdDiskIfaces); 5801 if (RT_SUCCESS(vrc)) 5802 vrc = VDClose(hdd, true /* fDelete */); 5803 5804 if (RT_FAILURE(vrc)) 5805 { 5806 throw setError(E_FAIL, 5807 tr("Could not delete the hard disk storage unit '%s'%s"), 5808 location.raw(), that->vdError(vrc).raw()); 5809 } 5810 5811 /* next, create it again */ 5812 vrc = VDOpen(hdd, parentFormat.c_str(), parentLocation.c_str(), 5813 VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO, 5814 that->m->vdDiskIfaces); 5815 if (RT_FAILURE(vrc)) 5816 { 5817 throw setError(E_FAIL, 5818 tr("Could not open the hard disk storage unit '%s'%s"), 5819 parentLocation.raw(), that->vdError(vrc).raw()); 5820 } 5821 5822 vrc = VDCreateDiff(hdd, format.c_str(), location.c_str(), 5823 /// @todo use the same image variant as before 5824 VD_IMAGE_FLAGS_NONE, 5825 NULL, id.raw(), 5826 parentId.raw(), 5827 VD_OPEN_FLAGS_NORMAL, 5828 that->m->vdDiskIfaces, 5829 vdOperationIfaces); 5830 if (RT_FAILURE(vrc)) 5831 { 5832 throw setError(E_FAIL, 5833 tr("Could not create the differencing hard disk storage unit '%s'%s"), 5834 location.raw(), that->vdError(vrc).raw()); 5835 } 5836 5837 size = VDGetFileSize(hdd, 1); 5838 logicalSize = VDGetSize(hdd, 1) / _1M; 5839 } 5840 catch (HRESULT aRC) { rc = aRC; } 5841 5842 VDDestroy(hdd); 5843 } 5844 catch (HRESULT aRC) { rc = aRC; } 5845 5846 thatLock.enter(); 5847 5848 that->m->size = size; 5849 that->m->logicalSize = logicalSize; 5850 5851 if (fIsAsync) 5852 { 5853 /* unlock ourselves when done */ 5854 HRESULT rc2 = that->UnlockWrite(NULL); 5855 AssertComRC(rc2); 5856 } 5857 5858 /* Note that in sync mode, it's the caller's responsibility to 5859 * unlock the hard disk */ 5860 5861 break; 5862 } 5863 5864 //////////////////////////////////////////////////////////////////////// 5971 rc = that->taskThreadReset((void*)vdOperationIfaces, fIsAsync); 5972 break; 5865 5973 5866 5974 case Task::Compact: 5867 { 5868 /* Lock all in {parent,child} order. The lock is also used as a 5869 * signal from the task initiator (which releases it only after 5870 * RTThreadCreate()) that we can start the job. */ 5871 AutoWriteLock thatLock(that COMMA_LOCKVAL_SRC_POS); 5872 5873 ImageChain *imgChain = task->d.images.get(); 5874 5875 try 5876 { 5877 PVBOXHDD hdd; 5878 int vrc = VDCreate(that->m->vdDiskIfaces, &hdd); 5879 ComAssertRCThrow(vrc, E_FAIL); 5880 5881 try 5882 { 5883 /* Open all hard disk images in the chain. */ 5884 MediaList::const_iterator last = imgChain->end(); 5885 last--; 5886 for (MediaList::const_iterator it = imgChain->begin(); 5887 it != imgChain->end(); 5888 ++it) 5889 { 5890 /* sanity check */ 5891 if (it == last) 5892 Assert((*it)->m->state == MediumState_LockedWrite); 5893 else 5894 Assert((*it)->m->state == MediumState_LockedRead); 5895 5896 /** Open all images but last in read-only mode. */ 5897 vrc = VDOpen(hdd, (*it)->m->strFormat.c_str(), 5898 (*it)->m->strLocationFull.c_str(), 5899 (it == last) ? VD_OPEN_FLAGS_NORMAL : VD_OPEN_FLAGS_READONLY, 5900 (*it)->m->vdDiskIfaces); 5901 if (RT_FAILURE(vrc)) 5902 { 5903 throw setError(E_FAIL, 5904 tr("Could not open the hard disk storage unit '%s'%s"), 5905 (*it)->m->strLocationFull.raw(), 5906 that->vdError(vrc).raw()); 5907 } 5908 } 5909 5910 Assert(that->m->state == MediumState_LockedWrite); 5911 5912 Utf8Str location(that->m->strLocationFull); 5913 5914 /* unlock before the potentially lengthy operation */ 5915 thatLock.leave(); 5916 5917 vrc = VDCompact(hdd, VD_LAST_IMAGE, vdOperationIfaces); 5918 if (RT_FAILURE(vrc)) 5919 { 5920 if (vrc == VERR_NOT_SUPPORTED) 5921 throw setError(VBOX_E_NOT_SUPPORTED, 5922 tr("Compacting is not yet supported for hard disk '%s'"), 5923 location.raw()); 5924 else if (vrc == VERR_NOT_IMPLEMENTED) 5925 throw setError(E_NOTIMPL, 5926 tr("Compacting is not implemented, hard disk '%s'"), 5927 location.raw()); 5928 else 5929 throw setError(E_FAIL, 5930 tr("Could not compact hard disk '%s'%s"), 5931 location.raw(), 5932 that->vdError(vrc).raw()); 5933 } 5934 } 5935 catch (HRESULT aRC) { rc = aRC; } 5936 5937 VDDestroy(hdd); 5938 } 5939 catch (HRESULT aRC) { rc = aRC; } 5940 5941 /* Everything is explicitly unlocked when the task exits, 5942 * as the task destruction also destroys the image chain. */ 5943 5944 break; 5945 } 5975 rc = that->taskThreadCompact(*task, (void*)vdOperationIfaces); 5976 break; 5946 5977 5947 5978 default: -
trunk/src/VBox/Main/include/MediumImpl.h
r25887 r25888 313 313 HRESULT taskThreadMerge(Task &task, void *pvdOperationIfaces, bool fIsAsync); 314 314 HRESULT taskThreadClone(Task &task, void *pvdOperationIfaces); 315 HRESULT taskThreadDelete(); 316 HRESULT taskThreadReset(void *pvdOperationIfaces, bool fIsAsync); 317 HRESULT taskThreadCompact(Task &task, void *pvdOperationIfaces); 315 318 316 319 static DECLCALLBACK(int) taskThread(RTTHREAD thread, void *pvUser);
Note:
See TracChangeset
for help on using the changeset viewer.