VirtualBox

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

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

Main/MediumLock: add method to retrieve requested lock mode

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

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