VirtualBox

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

Last change on this file since 47348 was 45595, checked in by vboxsync, 12 years ago

Main/MediumLock: delete the medium lock list when it is erased

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