summaryrefslogtreecommitdiffstats
path: root/src/VBox/Main/include/MediumLock.h
blob: d01fb9f365a99f05924213368c1560abbc2bc518 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
/* $Id: MediumLock.h $ */

/** @file
 *
 * VirtualBox medium object lock collections
 */

/*
 * Copyright (C) 2010-2023 Oracle and/or its affiliates.
 *
 * This file is part of VirtualBox base platform packages, as
 * available from https://www.virtualbox.org.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation, in version 3 of the
 * License.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, see <https://www.gnu.org/licenses>.
 *
 * SPDX-License-Identifier: GPL-3.0-only
 */

#ifndef MAIN_INCLUDED_MediumLock_h
#define MAIN_INCLUDED_MediumLock_h
#ifndef RT_WITHOUT_PRAGMA_ONCE
# pragma once
#endif

/* interface definitions */
#include "VBox/com/VirtualBox.h"
#include "VirtualBoxBase.h"
#include "AutoCaller.h"

#include <iprt/types.h>

#include <list>
#include <map>

class Medium;
class MediumAttachment;

/**
 * Single entry for medium lock lists. Has a medium object reference,
 * information about what kind of lock should be taken, and if it is
 * locked right now.
 */
class MediumLock
{
public:
    /**
     * Default medium lock constructor.
     */
    MediumLock();

    /**
     * Default medium lock destructor.
     */
    ~MediumLock();

    /**
     * Create a new medium lock description
     *
     * @param aMedium       Reference to medium object
     * @param aLockWrite    @c true means a write lock should be taken
     */
    MediumLock(const ComObjPtr<Medium> &aMedium, bool aLockWrite);

    /**
     * Copy constructor. Needed because we contain an AutoCaller
     * instance which is deliberately not copyable. The copy is not
     * marked as locked, so be careful.
     *
     * @param aMediumLock   Reference to source object.
     */
    MediumLock(const MediumLock &aMediumLock);

    /**
     * Update a medium lock description.
     *
     * @note May be used in locked state.
     *
     * @return COM status code
     * @param aLockWrite    @c true means a write lock should be taken
     */
    HRESULT UpdateLock(bool aLockWrite);

    /**
     * Get medium object reference.
     */
    const ComObjPtr<Medium> &GetMedium() const;

    /**
     * Get medium object lock request type.
     */
    bool GetLockRequest() const;

    /**
     * Check if this medium object has been locked by this MediumLock.
     */
    bool IsLocked() const;

    /**
     * Acquire a medium lock.
     *
     * @return COM status code
     * @param aIgnoreLockedMedia    If set ignore all media which is already
     *                              locked in an incompatible way.
     */
    HRESULT Lock(bool aIgnoreLockedMedia = false);

    /**
     * Release a medium lock.
     *
     * @return COM status code
     */
    HRESULT Unlock();

private:
    ComObjPtr<Medium> mMedium;
    ComPtr<IToken> mToken;
    AutoCaller mMediumCaller;
    bool mLockWrite;
    bool mIsLocked;
    /** Flag whether the medium was skipped when taking the locks.
     * Only existing and accessible media objects need to be locked. */
    bool mLockSkipped;
};


/**
 * Medium lock list. Meant for storing the ordered locking information
 * for a single medium chain.
 */
class MediumLockList
{
public:

    /* Base list data type. */
    typedef std::list<MediumLock> Base;

    /**
     * Default medium lock list constructor.
     */
    MediumLockList();

    /**
     * Default medium lock list destructor.
     */
    ~MediumLockList();

    /**
     * Checks if medium lock declaration list is empty.
     *
     * @return true if list is empty.
     */
    bool IsEmpty();

    /**
     * Add a new medium lock declaration to the end of the list.
     *
     * @note May be only used in unlocked state.
     *
     * @return COM status code
     * @param aMedium       Reference to medium object
     * @param aLockWrite    @c true means a write lock should be taken
     */
    HRESULT Append(const ComObjPtr<Medium> &aMedium, bool aLockWrite);

    /**
     * Add a new medium lock declaration to the beginning of the list.
     *
     * @note May be only used in unlocked state.
     *
     * @return COM status code
     * @param aMedium       Reference to medium object
     * @param aLockWrite    @c true means a write lock should be taken
     */
    HRESULT Prepend(const ComObjPtr<Medium> &aMedium, bool aLockWrite);

    /**
     * Update a medium lock declaration.
     *
     * @note May be used in locked state.
     *
     * @return COM status code
     * @param aMedium       Reference to medium object
     * @param aLockWrite    @c true means a write lock should be taken
     */
    HRESULT Update(const ComObjPtr<Medium> &aMedium, bool aLockWrite);

    /**
     * Remove a medium lock declaration and return an updated iterator.
     *
     * @note May be used in locked state.
     *
     * @return COM status code
     * @param aIt           Iterator for the element to remove
     */
    HRESULT RemoveByIterator(Base::iterator &aIt);

    /**
     * Clear all medium lock declarations.
     *
     * @note Implicitly unlocks all locks.
     *
     * @return COM status code
     */
    HRESULT Clear();

    /**
     * Get iterator begin() for base list.
     */
    Base::iterator GetBegin();

    /**
     * Get iterator end() for base list.
     */
    Base::iterator GetEnd();

    /**
     * Acquire all medium locks "atomically", i.e. all or nothing.
     *
     * @return COM status code
     * @param aSkipOverLockedMedia  If set ignore all media which is already
     *                              locked for reading or writing. For callers
     *                              which need to know which medium objects
     *                              have been locked by this lock list you
     *                              can iterate over the list and check the
     *                              MediumLock state.
     */
    HRESULT Lock(bool aSkipOverLockedMedia = false);

    /**
     * Release all medium locks.
     *
     * @return COM status code
     */
    HRESULT Unlock();

private:
    Base mMediumLocks;
    bool mIsLocked;
};

/**
 * Medium lock list map. Meant for storing a collection of lock lists.
 * The usual use case is creating such a map when locking all medium chains
 * belonging to one VM, however that's not the limit. Be creative.
 */
class MediumLockListMap
{
public:

    /**
     * Default medium lock list map constructor.
     */
    MediumLockListMap();

    /**
     * Default medium lock list map destructor.
     */
    ~MediumLockListMap();

    /**
     * Checks if medium lock list map is empty.
     *
     * @return true if list is empty.
     */
    bool IsEmpty();

    /**
     * Insert a new medium lock list into the map.
     *
     * @note May be only used in unlocked state.
     *
     * @return COM status code
     * @param aMediumAttachment Reference to medium attachment object, the key.
     * @param aMediumLockList   Reference to medium lock list object
     */
    HRESULT Insert(const ComObjPtr<MediumAttachment> &aMediumAttachment, MediumLockList *aMediumLockList);

    /**
     * Replace the medium lock list key by a different one.
     *
     * @note May be used in locked state.
     *
     * @return COM status code
     * @param aMediumAttachmentOld  Reference to medium attachment object.
     * @param aMediumAttachmentNew  Reference to medium attachment object.
     */
    HRESULT ReplaceKey(const ComObjPtr<MediumAttachment> &aMediumAttachmentOld, const ComObjPtr<MediumAttachment> &aMediumAttachmentNew);

    /**
     * Remove a medium lock list from the map. The list will get deleted.
     *
     * @note May be only used in unlocked state.
     *
     * @return COM status code
     * @param aMediumAttachment Reference to medium attachment object, the key.
     */
    HRESULT Remove(const ComObjPtr<MediumAttachment> &aMediumAttachment);

    /**
     * Clear all medium lock declarations in this map.
     *
     * @note Implicitly unlocks all locks.
     *
     * @return COM status code
     */
    HRESULT Clear();

    /**
     * Get the medium lock list identified by the given key.
     *
     * @note May be used in locked state.
     *
     * @return COM status code
     * @param aMediumAttachment     Key for medium attachment object.
     * @param aMediumLockList       Out: medium attachment object reference.
     */
    HRESULT Get(const ComObjPtr<MediumAttachment> &aMediumAttachment, MediumLockList * &aMediumLockList);

    /**
     * Acquire all medium locks "atomically", i.e. all or nothing.
     *
     * @return COM status code
     */
    HRESULT Lock();

    /**
     * Release all medium locks.
     *
     * @return COM status code
     */
    HRESULT Unlock();

    /** Introspection. */
    bool IsLocked(void) const { return mIsLocked; }

private:
    typedef std::map<ComObjPtr<MediumAttachment>, MediumLockList *> Base;
    Base mMediumLocks;
    bool mIsLocked;
};

#endif /* !MAIN_INCLUDED_MediumLock_h */
/* vi: set tabstop=4 shiftwidth=4 expandtab: */