VirtualBox

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

Last change on this file since 63378 was 62485, checked in by vboxsync, 8 years ago

(C) 2016

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