VirtualBox

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

Last change on this file since 28800 was 28800, checked in by vboxsync, 14 years ago

Automated rebranding to Oracle copyright/license strings via filemuncher

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 8.7 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 if (aLockWrite == mLockWrite)
49 return S_OK;
50 if (mIsLocked)
51 {
52 HRESULT rc = Unlock();
53 if (FAILED(rc))
54 {
55 Lock();
56 return rc;
57 }
58 mLockWrite = aLockWrite;
59 rc = Lock();
60 if (FAILED(rc))
61 {
62 mLockWrite = !mLockWrite;
63 Lock();
64 return rc;
65 }
66 return S_OK;
67 }
68
69 mLockWrite = aLockWrite;
70 return S_OK;
71}
72
73const ComObjPtr<Medium> &MediumLock::GetMedium() const
74{
75 return mMedium;
76}
77
78bool MediumLock::GetLockRequest() const
79{
80 return mLockWrite;
81}
82
83HRESULT MediumLock::Lock()
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->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 rc = mMedium->LockWrite(NULL);
111 else
112 rc = mMedium->LockRead(NULL);
113 }
114 if (SUCCEEDED(rc))
115 {
116 mIsLocked = true;
117 return S_OK;
118 }
119 else
120 {
121 mMediumCaller.attach(NULL);
122 return VBOX_E_INVALID_OBJECT_STATE;
123 }
124}
125
126HRESULT MediumLock::Unlock()
127{
128 HRESULT rc = S_OK;
129 if (mIsLocked && !mLockSkipped)
130 {
131 if (mLockWrite)
132 rc = mMedium->UnlockWrite(NULL);
133 else
134 rc = mMedium->UnlockRead(NULL);
135 }
136 mMediumCaller.attach(NULL);
137 mLockSkipped = false;
138 mIsLocked = false;
139 return rc;
140}
141
142MediumLockList::MediumLockList()
143{
144 mIsLocked = false;
145}
146
147MediumLockList::~MediumLockList()
148{
149 Clear();
150 // rest is done by the list object's destructor
151}
152
153bool MediumLockList::IsEmpty()
154{
155 return mMediumLocks.empty();
156}
157
158HRESULT MediumLockList::Append(const ComObjPtr<Medium> &aMedium, bool aLockWrite)
159{
160 if (mIsLocked)
161 return VBOX_E_INVALID_OBJECT_STATE;
162 mMediumLocks.push_back(MediumLock(aMedium, aLockWrite));
163 return S_OK;
164}
165
166HRESULT MediumLockList::Prepend(const ComObjPtr<Medium> &aMedium, bool aLockWrite)
167{
168 if (mIsLocked)
169 return VBOX_E_INVALID_OBJECT_STATE;
170 mMediumLocks.push_front(MediumLock(aMedium, aLockWrite));
171 return S_OK;
172}
173
174HRESULT MediumLockList::Update(const ComObjPtr<Medium> &aMedium, bool aLockWrite)
175{
176 for (MediumLockList::Base::iterator it = mMediumLocks.begin();
177 it != mMediumLocks.end();
178 it++)
179 {
180 if (it->GetMedium() == aMedium)
181 return it->UpdateLock(aLockWrite);
182 }
183 return VBOX_E_INVALID_OBJECT_STATE;
184}
185
186HRESULT MediumLockList::RemoveByIterator(Base::iterator &aIt)
187{
188 HRESULT rc = aIt->Unlock();
189 aIt = mMediumLocks.erase(aIt);
190 return rc;
191}
192
193HRESULT MediumLockList::Clear()
194{
195 HRESULT rc = Unlock();
196 mMediumLocks.clear();
197 return rc;
198}
199
200MediumLockList::Base::iterator MediumLockList::GetBegin()
201{
202 return mMediumLocks.begin();
203}
204
205MediumLockList::Base::iterator MediumLockList::GetEnd()
206{
207 return mMediumLocks.end();
208}
209
210HRESULT MediumLockList::Lock()
211{
212 if (mIsLocked)
213 return S_OK;
214 HRESULT rc = S_OK;
215 for (MediumLockList::Base::iterator it = mMediumLocks.begin();
216 it != mMediumLocks.end();
217 it++)
218 {
219 rc = it->Lock();
220 if (FAILED(rc))
221 {
222 for (MediumLockList::Base::iterator it2 = mMediumLocks.begin();
223 it2 != it;
224 it2++)
225 {
226 HRESULT rc2 = it2->Unlock();
227 AssertComRC(rc2);
228 }
229 break;
230 }
231 }
232 if (SUCCEEDED(rc))
233 mIsLocked = true;
234 return rc;
235}
236
237HRESULT MediumLockList::Unlock()
238{
239 if (!mIsLocked)
240 return S_OK;
241 HRESULT rc = S_OK;
242 for (MediumLockList::Base::iterator it = mMediumLocks.begin();
243 it != mMediumLocks.end();
244 it++)
245 {
246 HRESULT rc2 = it->Unlock();
247 if (SUCCEEDED(rc) && FAILED(rc2))
248 rc = rc2;
249 }
250 mIsLocked = false;
251 return rc;
252}
253
254
255MediumLockListMap::MediumLockListMap()
256{
257 mIsLocked = false;
258}
259
260MediumLockListMap::~MediumLockListMap()
261{
262 Clear();
263 // rest is done by the map object's destructor
264}
265
266bool MediumLockListMap::IsEmpty()
267{
268 return mMediumLocks.empty();
269}
270
271HRESULT MediumLockListMap::Insert(const ComObjPtr<MediumAttachment> &aMediumAttachment,
272 MediumLockList *aMediumLockList)
273{
274 if (mIsLocked)
275 return VBOX_E_INVALID_OBJECT_STATE;
276 mMediumLocks[aMediumAttachment] = aMediumLockList;
277 return S_OK;
278}
279
280HRESULT MediumLockListMap::ReplaceKey(const ComObjPtr<MediumAttachment> &aMediumAttachmentOld,
281 const ComObjPtr<MediumAttachment> &aMediumAttachmentNew)
282{
283 MediumLockListMap::Base::iterator it = mMediumLocks.find(aMediumAttachmentOld);
284 if (it == mMediumLocks.end())
285 return VBOX_E_INVALID_OBJECT_STATE;
286 MediumLockList *pMediumLockList = it->second;
287 mMediumLocks.erase(it);
288 mMediumLocks[aMediumAttachmentNew] = pMediumLockList;
289 return S_OK;
290}
291
292HRESULT MediumLockListMap::Remove(const ComObjPtr<MediumAttachment> &aMediumAttachment)
293{
294 MediumLockListMap::Base::iterator it = mMediumLocks.find(aMediumAttachment);
295 if (it == mMediumLocks.end())
296 return VBOX_E_INVALID_OBJECT_STATE;
297 mMediumLocks.erase(it);
298 return S_OK;
299}
300
301HRESULT MediumLockListMap::Clear()
302{
303 HRESULT rc = Unlock();
304 for (MediumLockListMap::Base::iterator it = mMediumLocks.begin();
305 it != mMediumLocks.end();
306 )
307 {
308 MediumLockList *pMediumLockList = it->second;
309 // need an incremented iterator as otherwise erasing invalidates it
310 mMediumLocks.erase(it++);
311 delete pMediumLockList;
312 }
313 return rc;
314}
315
316HRESULT MediumLockListMap::Get(const ComObjPtr<MediumAttachment> &aMediumAttachment,
317 MediumLockList * &aMediumLockList)
318{
319 MediumLockListMap::Base::iterator it = mMediumLocks.find(aMediumAttachment);
320 if (it == mMediumLocks.end())
321 {
322 aMediumLockList = NULL;
323 return VBOX_E_INVALID_OBJECT_STATE;
324 }
325 aMediumLockList = it->second;
326 return S_OK;
327}
328
329HRESULT MediumLockListMap::Lock()
330{
331 if (mIsLocked)
332 return S_OK;
333 HRESULT rc = S_OK;
334 for (MediumLockListMap::Base::const_iterator it = mMediumLocks.begin();
335 it != mMediumLocks.end();
336 it++)
337 {
338 rc = it->second->Lock();
339 if (FAILED(rc))
340 {
341 for (MediumLockListMap::Base::const_iterator it2 = mMediumLocks.begin();
342 it2 != it;
343 it2++)
344 {
345 HRESULT rc2 = it2->second->Unlock();
346 AssertComRC(rc2);
347 }
348 break;
349 }
350 }
351 if (SUCCEEDED(rc))
352 mIsLocked = true;
353 return rc;
354}
355
356HRESULT MediumLockListMap::Unlock()
357{
358 if (!mIsLocked)
359 return S_OK;
360 HRESULT rc = S_OK;
361 for (MediumLockListMap::Base::const_iterator it = mMediumLocks.begin();
362 it != mMediumLocks.end();
363 it++)
364 {
365 MediumLockList *pMediumLockList = it->second;
366 HRESULT rc2 = pMediumLockList->Unlock();
367 if (SUCCEEDED(rc) && FAILED(rc2))
368 rc = rc2;
369 }
370 mIsLocked = false;
371 return rc;
372}
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use