VirtualBox

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

Last change on this file since 28456 was 28353, checked in by vboxsync, 15 years ago

Main/MediumLock: header file update and implementation. Gets built and linked now even though it is not yet used.

  • 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 Sun Microsystems, Inc.
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 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
18 * Clara, CA 95054 USA or visit http://www.sun.com if you need
19 * additional information or have any questions.
20 */
21
22#include "MediumLock.h"
23#include "MediumImpl.h"
24#include "MediumAttachmentImpl.h"
25
26
27MediumLock::MediumLock()
28 : mMedium(NULL), mMediumCaller(NULL), mLockWrite(false),
29 mIsLocked(false), mLockSkipped(false)
30{
31}
32
33MediumLock::~MediumLock()
34{
35 Unlock();
36}
37
38MediumLock::MediumLock(const MediumLock &aMediumLock)
39 : mMedium(aMediumLock.mMedium), mMediumCaller(NULL),
40 mLockWrite(aMediumLock.mLockWrite), mIsLocked(false), mLockSkipped(false)
41{
42}
43
44MediumLock::MediumLock(const ComObjPtr<Medium> &aMedium, bool aLockWrite)
45 : mMedium(aMedium), mMediumCaller(NULL), mLockWrite(aLockWrite),
46 mIsLocked(false), mLockSkipped(false)
47{
48}
49
50HRESULT MediumLock::UpdateLock(bool aLockWrite)
51{
52 if (mIsLocked)
53 return VBOX_E_INVALID_OBJECT_STATE;
54 mLockWrite = aLockWrite;
55 return S_OK;
56}
57
58const ComObjPtr<Medium> &MediumLock::GetMedium() const
59{
60 return mMedium;
61}
62
63HRESULT MediumLock::Lock()
64{
65 if (mIsLocked)
66 return S_OK;
67
68 mMediumCaller.attach(mMedium);
69 if (FAILED(mMediumCaller.rc()))
70 {
71 mMediumCaller.attach(NULL);
72 return VBOX_E_INVALID_OBJECT_STATE;
73 }
74
75 HRESULT rc = S_OK;
76 MediumState_T state;
77 {
78 AutoReadLock alock(mMedium COMMA_LOCKVAL_SRC_POS);
79 state = mMedium->getState();
80 }
81 switch (state)
82 {
83 case MediumState_NotCreated:
84 case MediumState_Creating:
85 case MediumState_Deleting:
86 mLockSkipped = true;
87 break;
88 default:
89 if (mLockWrite)
90 rc = mMedium->LockWrite(NULL);
91 else
92 rc = mMedium->LockRead(NULL);
93 }
94 if (SUCCEEDED(rc))
95 {
96 mIsLocked = true;
97 return S_OK;
98 }
99 else
100 {
101 mMediumCaller.attach(NULL);
102 return VBOX_E_INVALID_OBJECT_STATE;
103 }
104}
105
106HRESULT MediumLock::Unlock()
107{
108 HRESULT rc = S_OK;
109 if (mIsLocked && !mLockSkipped)
110 {
111 if (mLockWrite)
112 rc = mMedium->UnlockWrite(NULL);
113 else
114 rc = mMedium->UnlockRead(NULL);
115 }
116 mMediumCaller.attach(NULL);
117 mLockSkipped = false;
118 mIsLocked = false;
119 return rc;
120}
121
122MediumLockList::MediumLockList()
123{
124 mIsLocked = false;
125}
126
127MediumLockList::~MediumLockList()
128{
129 Clear();
130 // rest is done by the list object's destructor
131}
132
133bool MediumLockList::IsEmpty()
134{
135 return mMediumLocks.empty();
136}
137
138HRESULT MediumLockList::Append(const ComObjPtr<Medium> &aMedium, bool aLockWrite)
139{
140 if (mIsLocked)
141 return VBOX_E_INVALID_OBJECT_STATE;
142 mMediumLocks.push_back(MediumLock(aMedium, aLockWrite));
143 return S_OK;
144}
145
146HRESULT MediumLockList::Prepend(const ComObjPtr<Medium> &aMedium, bool aLockWrite)
147{
148 if (mIsLocked)
149 return VBOX_E_INVALID_OBJECT_STATE;
150 mMediumLocks.push_front(MediumLock(aMedium, aLockWrite));
151 return S_OK;
152}
153
154HRESULT MediumLockList::Update(const ComObjPtr<Medium> &aMedium, bool aLockWrite)
155{
156 if (mIsLocked)
157 return VBOX_E_INVALID_OBJECT_STATE;
158 for (MediumLockList::Base::iterator it = mMediumLocks.begin();
159 it != mMediumLocks.end();
160 it++)
161 {
162 if (it->GetMedium() == aMedium)
163 return it->UpdateLock(aLockWrite);
164 }
165 return VBOX_E_INVALID_OBJECT_STATE;
166}
167
168HRESULT MediumLockList::RemoveByIterator(Base::iterator &aIt)
169{
170 HRESULT rc = aIt->Unlock();
171 aIt = mMediumLocks.erase(aIt);
172 return rc;
173}
174
175HRESULT MediumLockList::Clear()
176{
177 HRESULT rc = Unlock();
178 mMediumLocks.clear();
179 return rc;
180}
181
182MediumLockList::Base::iterator MediumLockList::GetBegin()
183{
184 return mMediumLocks.begin();
185}
186
187MediumLockList::Base::iterator MediumLockList::GetEnd()
188{
189 return mMediumLocks.end();
190}
191
192HRESULT MediumLockList::Lock()
193{
194 if (mIsLocked)
195 return S_OK;
196 HRESULT rc = S_OK;
197 for (MediumLockList::Base::iterator it = mMediumLocks.begin();
198 it != mMediumLocks.end();
199 it++)
200 {
201 rc = it->Lock();
202 if (FAILED(rc))
203 {
204 for (MediumLockList::Base::iterator it2 = mMediumLocks.begin();
205 it2 != it;
206 it2++)
207 {
208 HRESULT rc2 = it2->Unlock();
209 AssertComRC(rc2);
210 }
211 break;
212 }
213 }
214 if (SUCCEEDED(rc))
215 mIsLocked = true;
216 return rc;
217}
218
219HRESULT MediumLockList::Unlock()
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 HRESULT rc2 = it->Unlock();
229 if (SUCCEEDED(rc) && FAILED(rc2))
230 rc = rc2;
231 }
232 mIsLocked = false;
233 return rc;
234}
235
236
237MediumLockListMap::MediumLockListMap()
238{
239 mIsLocked = false;
240}
241
242MediumLockListMap::~MediumLockListMap()
243{
244 Clear();
245 // rest is done by the map object's destructor
246}
247
248bool MediumLockListMap::IsEmpty()
249{
250 return mMediumLocks.empty();
251}
252
253HRESULT MediumLockListMap::Insert(const ComObjPtr<MediumAttachment> &aMediumAttachment,
254 MediumLockList *aMediumLockList)
255{
256 if (mIsLocked)
257 return VBOX_E_INVALID_OBJECT_STATE;
258 mMediumLocks[aMediumAttachment] = aMediumLockList;
259 return S_OK;
260}
261
262HRESULT MediumLockListMap::ReplaceKey(const ComObjPtr<MediumAttachment> &aMediumAttachmentOld,
263 const ComObjPtr<MediumAttachment> &aMediumAttachmentNew)
264{
265 MediumLockListMap::Base::iterator it = mMediumLocks.find(aMediumAttachmentOld);
266 if (it == mMediumLocks.end())
267 return VBOX_E_INVALID_OBJECT_STATE;
268 MediumLockList *pMediumLockList = it->second;
269 mMediumLocks.erase(it);
270 mMediumLocks[aMediumAttachmentNew] = pMediumLockList;
271 return S_OK;
272}
273
274HRESULT MediumLockListMap::Remove(const ComObjPtr<MediumAttachment> &aMediumAttachment)
275{
276 MediumLockListMap::Base::iterator it = mMediumLocks.find(aMediumAttachment);
277 if (it == mMediumLocks.end())
278 return VBOX_E_INVALID_OBJECT_STATE;
279 mMediumLocks.erase(it);
280 return S_OK;
281}
282
283HRESULT MediumLockListMap::Clear()
284{
285 HRESULT rc = Unlock();
286 for (MediumLockListMap::Base::iterator it = mMediumLocks.begin();
287 it != mMediumLocks.end();
288 )
289 {
290 MediumLockList *pMediumLockList = it->second;
291 // need an incremented iterator as otherwise erasing invalidates it
292 mMediumLocks.erase(it++);
293 delete pMediumLockList;
294 }
295 return rc;
296}
297
298HRESULT MediumLockListMap::Get(const ComObjPtr<MediumAttachment> &aMediumAttachment,
299 MediumLockList * &aMediumLockList)
300{
301 MediumLockListMap::Base::iterator it = mMediumLocks.find(aMediumAttachment);
302 if (it == mMediumLocks.end())
303 {
304 aMediumLockList = NULL;
305 return VBOX_E_INVALID_OBJECT_STATE;
306 }
307 aMediumLockList = it->second;
308 return S_OK;
309}
310
311HRESULT MediumLockListMap::Lock()
312{
313 if (mIsLocked)
314 return S_OK;
315 HRESULT rc = S_OK;
316 for (MediumLockListMap::Base::const_iterator it = mMediumLocks.begin();
317 it != mMediumLocks.end();
318 it++)
319 {
320 rc = it->second->Lock();
321 if (FAILED(rc))
322 {
323 for (MediumLockListMap::Base::const_iterator it2 = mMediumLocks.begin();
324 it2 != it;
325 it2++)
326 {
327 HRESULT rc2 = it2->second->Unlock();
328 AssertComRC(rc2);
329 }
330 break;
331 }
332 }
333 if (SUCCEEDED(rc))
334 mIsLocked = true;
335 return rc;
336}
337
338HRESULT MediumLockListMap::Unlock()
339{
340 if (!mIsLocked)
341 return S_OK;
342 HRESULT rc = S_OK;
343 for (MediumLockListMap::Base::const_iterator it = mMediumLocks.begin();
344 it != mMediumLocks.end();
345 it++)
346 {
347 MediumLockList *pMediumLockList = it->second;
348 HRESULT rc2 = pMediumLockList->Unlock();
349 if (SUCCEEDED(rc) && FAILED(rc2))
350 rc = rc2;
351 }
352 mIsLocked = false;
353 return rc;
354}
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