VirtualBox

source: vbox/trunk/src/VBox/Main/src-server/MediumLock.cpp@ 54474

Last change on this file since 54474 was 49795, checked in by vboxsync, 11 years ago

6813 - stage 3 rev 1

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 9.1 KB
Line 
1/** @file
2 *
3 * Medium lock management helper classes
4 */
5
6/*
7 * Copyright (C) 2010-2013 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
77bool MediumLock::IsLocked() const
78{
79 return mIsLocked;
80}
81
82HRESULT MediumLock::Lock(bool aIgnoreLockedMedia)
83{
84 if (mIsLocked)
85 return S_OK;
86
87 mMediumCaller.attach(mMedium);
88 if (FAILED(mMediumCaller.rc()))
89 {
90 mMediumCaller.attach(NULL);
91 return VBOX_E_INVALID_OBJECT_STATE;
92 }
93
94 HRESULT rc = S_OK;
95 MediumState_T state;
96 {
97 AutoReadLock alock(mMedium COMMA_LOCKVAL_SRC_POS);
98 state = mMedium->i_getState();
99 }
100 switch (state)
101 {
102 case MediumState_NotCreated:
103 case MediumState_Creating:
104 case MediumState_Deleting:
105 mLockSkipped = true;
106 break;
107 default:
108 if (mLockWrite)
109 {
110 if (aIgnoreLockedMedia && ( state == MediumState_LockedRead
111 || state == MediumState_LockedWrite))
112 return S_OK;
113 else
114 rc = mMedium->LockWrite(mToken.asOutParam());
115 }
116 else
117 {
118 if (aIgnoreLockedMedia && state == MediumState_LockedWrite)
119 return S_OK;
120 else
121 rc = mMedium->LockRead(mToken.asOutParam());
122 }
123 }
124 if (SUCCEEDED(rc))
125 {
126 mIsLocked = true;
127 return S_OK;
128 }
129 else
130 {
131 mMediumCaller.attach(NULL);
132 return VBOX_E_INVALID_OBJECT_STATE;
133 }
134}
135
136HRESULT MediumLock::Unlock()
137{
138 HRESULT rc = S_OK;
139 if (mIsLocked && !mLockSkipped && mToken)
140 {
141 mToken->Abandon();
142 mToken.setNull();
143 }
144 mMediumCaller.attach(NULL);
145 mLockSkipped = false;
146 mIsLocked = false;
147 return rc;
148}
149
150MediumLockList::MediumLockList()
151{
152 mIsLocked = false;
153}
154
155MediumLockList::~MediumLockList()
156{
157 Clear();
158 // rest is done by the list object's destructor
159}
160
161bool MediumLockList::IsEmpty()
162{
163 return mMediumLocks.empty();
164}
165
166HRESULT MediumLockList::Append(const ComObjPtr<Medium> &aMedium, bool aLockWrite)
167{
168 if (mIsLocked)
169 return VBOX_E_INVALID_OBJECT_STATE;
170 mMediumLocks.push_back(MediumLock(aMedium, aLockWrite));
171 return S_OK;
172}
173
174HRESULT MediumLockList::Prepend(const ComObjPtr<Medium> &aMedium, bool aLockWrite)
175{
176 if (mIsLocked)
177 return VBOX_E_INVALID_OBJECT_STATE;
178 mMediumLocks.push_front(MediumLock(aMedium, aLockWrite));
179 return S_OK;
180}
181
182HRESULT MediumLockList::Update(const ComObjPtr<Medium> &aMedium, bool aLockWrite)
183{
184 for (MediumLockList::Base::iterator it = mMediumLocks.begin();
185 it != mMediumLocks.end();
186 it++)
187 {
188 if (it->GetMedium() == aMedium)
189 return it->UpdateLock(aLockWrite);
190 }
191 return VBOX_E_INVALID_OBJECT_STATE;
192}
193
194HRESULT MediumLockList::RemoveByIterator(Base::iterator &aIt)
195{
196 HRESULT rc = aIt->Unlock();
197 aIt = mMediumLocks.erase(aIt);
198 return rc;
199}
200
201HRESULT MediumLockList::Clear()
202{
203 HRESULT rc = Unlock();
204 mMediumLocks.clear();
205 return rc;
206}
207
208MediumLockList::Base::iterator MediumLockList::GetBegin()
209{
210 return mMediumLocks.begin();
211}
212
213MediumLockList::Base::iterator MediumLockList::GetEnd()
214{
215 return mMediumLocks.end();
216}
217
218HRESULT MediumLockList::Lock(bool fSkipOverLockedMedia /* = false */)
219{
220 if (mIsLocked)
221 return S_OK;
222 HRESULT rc = S_OK;
223 for (MediumLockList::Base::iterator it = mMediumLocks.begin();
224 it != mMediumLocks.end();
225 it++)
226 {
227 rc = it->Lock(fSkipOverLockedMedia);
228 if (FAILED(rc))
229 {
230 for (MediumLockList::Base::iterator it2 = mMediumLocks.begin();
231 it2 != it;
232 it2++)
233 {
234 HRESULT rc2 = it2->Unlock();
235 AssertComRC(rc2);
236 }
237 break;
238 }
239 }
240 if (SUCCEEDED(rc))
241 mIsLocked = true;
242 return rc;
243}
244
245HRESULT MediumLockList::Unlock()
246{
247 if (!mIsLocked)
248 return S_OK;
249 HRESULT rc = S_OK;
250 for (MediumLockList::Base::iterator it = mMediumLocks.begin();
251 it != mMediumLocks.end();
252 it++)
253 {
254 HRESULT rc2 = it->Unlock();
255 if (SUCCEEDED(rc) && FAILED(rc2))
256 rc = rc2;
257 }
258 mIsLocked = false;
259 return rc;
260}
261
262
263MediumLockListMap::MediumLockListMap()
264{
265 mIsLocked = false;
266}
267
268MediumLockListMap::~MediumLockListMap()
269{
270 Clear();
271 // rest is done by the map object's destructor
272}
273
274bool MediumLockListMap::IsEmpty()
275{
276 return mMediumLocks.empty();
277}
278
279HRESULT MediumLockListMap::Insert(const ComObjPtr<MediumAttachment> &aMediumAttachment,
280 MediumLockList *aMediumLockList)
281{
282 if (mIsLocked)
283 return VBOX_E_INVALID_OBJECT_STATE;
284 mMediumLocks[aMediumAttachment] = aMediumLockList;
285 return S_OK;
286}
287
288HRESULT MediumLockListMap::ReplaceKey(const ComObjPtr<MediumAttachment> &aMediumAttachmentOld,
289 const ComObjPtr<MediumAttachment> &aMediumAttachmentNew)
290{
291 MediumLockListMap::Base::iterator it = mMediumLocks.find(aMediumAttachmentOld);
292 if (it == mMediumLocks.end())
293 return VBOX_E_INVALID_OBJECT_STATE;
294 MediumLockList *pMediumLockList = it->second;
295 mMediumLocks.erase(it);
296 mMediumLocks[aMediumAttachmentNew] = pMediumLockList;
297 return S_OK;
298}
299
300HRESULT MediumLockListMap::Remove(const ComObjPtr<MediumAttachment> &aMediumAttachment)
301{
302 MediumLockListMap::Base::iterator it = mMediumLocks.find(aMediumAttachment);
303 if (it == mMediumLocks.end())
304 return VBOX_E_INVALID_OBJECT_STATE;
305 MediumLockList *pMediumLockList = it->second;
306 mMediumLocks.erase(it);
307 delete pMediumLockList;
308 return S_OK;
309}
310
311HRESULT MediumLockListMap::Clear()
312{
313 HRESULT rc = Unlock();
314 for (MediumLockListMap::Base::iterator it = mMediumLocks.begin();
315 it != mMediumLocks.end();
316 )
317 {
318 MediumLockList *pMediumLockList = it->second;
319 // need an incremented iterator as otherwise erasing invalidates it
320 mMediumLocks.erase(it++);
321 delete pMediumLockList;
322 }
323 return rc;
324}
325
326HRESULT MediumLockListMap::Get(const ComObjPtr<MediumAttachment> &aMediumAttachment,
327 MediumLockList * &aMediumLockList)
328{
329 MediumLockListMap::Base::iterator it = mMediumLocks.find(aMediumAttachment);
330 if (it == mMediumLocks.end())
331 {
332 aMediumLockList = NULL;
333 return VBOX_E_INVALID_OBJECT_STATE;
334 }
335 aMediumLockList = it->second;
336 return S_OK;
337}
338
339HRESULT MediumLockListMap::Lock()
340{
341 if (mIsLocked)
342 return S_OK;
343 HRESULT rc = S_OK;
344 for (MediumLockListMap::Base::const_iterator it = mMediumLocks.begin();
345 it != mMediumLocks.end();
346 it++)
347 {
348 rc = it->second->Lock();
349 if (FAILED(rc))
350 {
351 for (MediumLockListMap::Base::const_iterator it2 = mMediumLocks.begin();
352 it2 != it;
353 it2++)
354 {
355 HRESULT rc2 = it2->second->Unlock();
356 AssertComRC(rc2);
357 }
358 break;
359 }
360 }
361 if (SUCCEEDED(rc))
362 mIsLocked = true;
363 return rc;
364}
365
366HRESULT MediumLockListMap::Unlock()
367{
368 if (!mIsLocked)
369 return S_OK;
370 HRESULT rc = S_OK;
371 for (MediumLockListMap::Base::const_iterator it = mMediumLocks.begin();
372 it != mMediumLocks.end();
373 it++)
374 {
375 MediumLockList *pMediumLockList = it->second;
376 HRESULT rc2 = pMediumLockList->Unlock();
377 if (SUCCEEDED(rc) && FAILED(rc2))
378 rc = rc2;
379 }
380 mIsLocked = false;
381 return rc;
382}
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