VirtualBox

source: vbox/trunk/src/VBox/Main/MediumLock.cpp@ 33973

Last change on this file since 33973 was 28835, checked in by vboxsync, 15 years ago

Main: live snapshot merging. initially limited to forward merging (i.e. everything but the first snapshot can be deleted)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 8.5 KB
Line 
1/** @file
2 *
3 * Medium lock management helper classes
4 */
5
6/*
7 * Copyright (C) 2010 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18#include "MediumLock.h"
19#include "MediumImpl.h"
20#include "MediumAttachmentImpl.h"
21
22
23MediumLock::MediumLock()
24 : mMedium(NULL), mMediumCaller(NULL), mLockWrite(false),
25 mIsLocked(false), mLockSkipped(false)
26{
27}
28
29MediumLock::~MediumLock()
30{
31 Unlock();
32}
33
34MediumLock::MediumLock(const MediumLock &aMediumLock)
35 : mMedium(aMediumLock.mMedium), mMediumCaller(NULL),
36 mLockWrite(aMediumLock.mLockWrite), mIsLocked(false), mLockSkipped(false)
37{
38}
39
40MediumLock::MediumLock(const ComObjPtr<Medium> &aMedium, bool aLockWrite)
41 : mMedium(aMedium), mMediumCaller(NULL), mLockWrite(aLockWrite),
42 mIsLocked(false), mLockSkipped(false)
43{
44}
45
46HRESULT MediumLock::UpdateLock(bool aLockWrite)
47{
48 bool fPrevLockWrite = mLockWrite;
49 if (mIsLocked)
50 {
51 Unlock();
52 mLockWrite = aLockWrite;
53 HRESULT rc = Lock();
54 if (FAILED(rc))
55 {
56 mLockWrite = fPrevLockWrite;
57 Lock();
58 return rc;
59 }
60 return S_OK;
61 }
62
63 mLockWrite = aLockWrite;
64 return S_OK;
65}
66
67const ComObjPtr<Medium> &MediumLock::GetMedium() const
68{
69 return mMedium;
70}
71
72bool MediumLock::GetLockRequest() const
73{
74 return mLockWrite;
75}
76
77HRESULT MediumLock::Lock()
78{
79 if (mIsLocked)
80 return S_OK;
81
82 mMediumCaller.attach(mMedium);
83 if (FAILED(mMediumCaller.rc()))
84 {
85 mMediumCaller.attach(NULL);
86 return VBOX_E_INVALID_OBJECT_STATE;
87 }
88
89 HRESULT rc = S_OK;
90 MediumState_T state;
91 {
92 AutoReadLock alock(mMedium COMMA_LOCKVAL_SRC_POS);
93 state = mMedium->getState();
94 }
95 switch (state)
96 {
97 case MediumState_NotCreated:
98 case MediumState_Creating:
99 case MediumState_Deleting:
100 mLockSkipped = true;
101 break;
102 default:
103 if (mLockWrite)
104 rc = mMedium->LockWrite(NULL);
105 else
106 rc = mMedium->LockRead(NULL);
107 }
108 if (SUCCEEDED(rc))
109 {
110 mIsLocked = true;
111 return S_OK;
112 }
113 else
114 {
115 mMediumCaller.attach(NULL);
116 return VBOX_E_INVALID_OBJECT_STATE;
117 }
118}
119
120HRESULT MediumLock::Unlock()
121{
122 HRESULT rc = S_OK;
123 if (mIsLocked && !mLockSkipped)
124 {
125 if (mLockWrite)
126 rc = mMedium->UnlockWrite(NULL);
127 else
128 rc = mMedium->UnlockRead(NULL);
129 }
130 mMediumCaller.attach(NULL);
131 mLockSkipped = false;
132 mIsLocked = false;
133 return rc;
134}
135
136MediumLockList::MediumLockList()
137{
138 mIsLocked = false;
139}
140
141MediumLockList::~MediumLockList()
142{
143 Clear();
144 // rest is done by the list object's destructor
145}
146
147bool MediumLockList::IsEmpty()
148{
149 return mMediumLocks.empty();
150}
151
152HRESULT MediumLockList::Append(const ComObjPtr<Medium> &aMedium, bool aLockWrite)
153{
154 if (mIsLocked)
155 return VBOX_E_INVALID_OBJECT_STATE;
156 mMediumLocks.push_back(MediumLock(aMedium, aLockWrite));
157 return S_OK;
158}
159
160HRESULT MediumLockList::Prepend(const ComObjPtr<Medium> &aMedium, bool aLockWrite)
161{
162 if (mIsLocked)
163 return VBOX_E_INVALID_OBJECT_STATE;
164 mMediumLocks.push_front(MediumLock(aMedium, aLockWrite));
165 return S_OK;
166}
167
168HRESULT MediumLockList::Update(const ComObjPtr<Medium> &aMedium, bool aLockWrite)
169{
170 for (MediumLockList::Base::iterator it = mMediumLocks.begin();
171 it != mMediumLocks.end();
172 it++)
173 {
174 if (it->GetMedium() == aMedium)
175 return it->UpdateLock(aLockWrite);
176 }
177 return VBOX_E_INVALID_OBJECT_STATE;
178}
179
180HRESULT MediumLockList::RemoveByIterator(Base::iterator &aIt)
181{
182 HRESULT rc = aIt->Unlock();
183 aIt = mMediumLocks.erase(aIt);
184 return rc;
185}
186
187HRESULT MediumLockList::Clear()
188{
189 HRESULT rc = Unlock();
190 mMediumLocks.clear();
191 return rc;
192}
193
194MediumLockList::Base::iterator MediumLockList::GetBegin()
195{
196 return mMediumLocks.begin();
197}
198
199MediumLockList::Base::iterator MediumLockList::GetEnd()
200{
201 return mMediumLocks.end();
202}
203
204HRESULT MediumLockList::Lock()
205{
206 if (mIsLocked)
207 return S_OK;
208 HRESULT rc = S_OK;
209 for (MediumLockList::Base::iterator it = mMediumLocks.begin();
210 it != mMediumLocks.end();
211 it++)
212 {
213 rc = it->Lock();
214 if (FAILED(rc))
215 {
216 for (MediumLockList::Base::iterator it2 = mMediumLocks.begin();
217 it2 != it;
218 it2++)
219 {
220 HRESULT rc2 = it2->Unlock();
221 AssertComRC(rc2);
222 }
223 break;
224 }
225 }
226 if (SUCCEEDED(rc))
227 mIsLocked = true;
228 return rc;
229}
230
231HRESULT MediumLockList::Unlock()
232{
233 if (!mIsLocked)
234 return S_OK;
235 HRESULT rc = S_OK;
236 for (MediumLockList::Base::iterator it = mMediumLocks.begin();
237 it != mMediumLocks.end();
238 it++)
239 {
240 HRESULT rc2 = it->Unlock();
241 if (SUCCEEDED(rc) && FAILED(rc2))
242 rc = rc2;
243 }
244 mIsLocked = false;
245 return rc;
246}
247
248
249MediumLockListMap::MediumLockListMap()
250{
251 mIsLocked = false;
252}
253
254MediumLockListMap::~MediumLockListMap()
255{
256 Clear();
257 // rest is done by the map object's destructor
258}
259
260bool MediumLockListMap::IsEmpty()
261{
262 return mMediumLocks.empty();
263}
264
265HRESULT MediumLockListMap::Insert(const ComObjPtr<MediumAttachment> &aMediumAttachment,
266 MediumLockList *aMediumLockList)
267{
268 if (mIsLocked)
269 return VBOX_E_INVALID_OBJECT_STATE;
270 mMediumLocks[aMediumAttachment] = aMediumLockList;
271 return S_OK;
272}
273
274HRESULT MediumLockListMap::ReplaceKey(const ComObjPtr<MediumAttachment> &aMediumAttachmentOld,
275 const ComObjPtr<MediumAttachment> &aMediumAttachmentNew)
276{
277 MediumLockListMap::Base::iterator it = mMediumLocks.find(aMediumAttachmentOld);
278 if (it == mMediumLocks.end())
279 return VBOX_E_INVALID_OBJECT_STATE;
280 MediumLockList *pMediumLockList = it->second;
281 mMediumLocks.erase(it);
282 mMediumLocks[aMediumAttachmentNew] = pMediumLockList;
283 return S_OK;
284}
285
286HRESULT MediumLockListMap::Remove(const ComObjPtr<MediumAttachment> &aMediumAttachment)
287{
288 MediumLockListMap::Base::iterator it = mMediumLocks.find(aMediumAttachment);
289 if (it == mMediumLocks.end())
290 return VBOX_E_INVALID_OBJECT_STATE;
291 mMediumLocks.erase(it);
292 return S_OK;
293}
294
295HRESULT MediumLockListMap::Clear()
296{
297 HRESULT rc = Unlock();
298 for (MediumLockListMap::Base::iterator it = mMediumLocks.begin();
299 it != mMediumLocks.end();
300 )
301 {
302 MediumLockList *pMediumLockList = it->second;
303 // need an incremented iterator as otherwise erasing invalidates it
304 mMediumLocks.erase(it++);
305 delete pMediumLockList;
306 }
307 return rc;
308}
309
310HRESULT MediumLockListMap::Get(const ComObjPtr<MediumAttachment> &aMediumAttachment,
311 MediumLockList * &aMediumLockList)
312{
313 MediumLockListMap::Base::iterator it = mMediumLocks.find(aMediumAttachment);
314 if (it == mMediumLocks.end())
315 {
316 aMediumLockList = NULL;
317 return VBOX_E_INVALID_OBJECT_STATE;
318 }
319 aMediumLockList = it->second;
320 return S_OK;
321}
322
323HRESULT MediumLockListMap::Lock()
324{
325 if (mIsLocked)
326 return S_OK;
327 HRESULT rc = S_OK;
328 for (MediumLockListMap::Base::const_iterator it = mMediumLocks.begin();
329 it != mMediumLocks.end();
330 it++)
331 {
332 rc = it->second->Lock();
333 if (FAILED(rc))
334 {
335 for (MediumLockListMap::Base::const_iterator it2 = mMediumLocks.begin();
336 it2 != it;
337 it2++)
338 {
339 HRESULT rc2 = it2->second->Unlock();
340 AssertComRC(rc2);
341 }
342 break;
343 }
344 }
345 if (SUCCEEDED(rc))
346 mIsLocked = true;
347 return rc;
348}
349
350HRESULT MediumLockListMap::Unlock()
351{
352 if (!mIsLocked)
353 return S_OK;
354 HRESULT rc = S_OK;
355 for (MediumLockListMap::Base::const_iterator it = mMediumLocks.begin();
356 it != mMediumLocks.end();
357 it++)
358 {
359 MediumLockList *pMediumLockList = it->second;
360 HRESULT rc2 = pMediumLockList->Unlock();
361 if (SUCCEEDED(rc) && FAILED(rc2))
362 rc = rc2;
363 }
364 mIsLocked = false;
365 return rc;
366}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette