~ubuntu-branches/ubuntu/raring/virtualbox-ose/raring

« back to all changes in this revision

Viewing changes to src/VBox/Main/MediumAttachmentImpl.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Felix Geyer
  • Date: 2011-01-30 23:27:25 UTC
  • mfrom: (0.3.12 upstream)
  • Revision ID: james.westby@ubuntu.com-20110130232725-2ouajjd2ggdet0zd
Tags: 4.0.2-dfsg-1ubuntu1
* Merge from Debian unstable, remaining changes:
  - Add Apport hook.
    - debian/virtualbox-ose.files/source_virtualbox-ose.py
    - debian/virtualbox-ose.install
  - Drop *-source packages.
* Drop ubuntu-01-fix-build-gcc45.patch, fixed upstream.
* Drop ubuntu-02-as-needed.patch, added to the Debian package.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/** @file
2
 
 *
3
 
 * VirtualBox COM class implementation
4
 
 */
5
 
 
6
 
/*
7
 
 * Copyright (C) 2006-2009 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 "MediumAttachmentImpl.h"
19
 
#include "MachineImpl.h"
20
 
#include "MediumImpl.h"
21
 
#include "Global.h"
22
 
 
23
 
#include "AutoCaller.h"
24
 
#include "Logging.h"
25
 
 
26
 
////////////////////////////////////////////////////////////////////////////////
27
 
//
28
 
// private member data definition
29
 
//
30
 
////////////////////////////////////////////////////////////////////////////////
31
 
 
32
 
struct BackupableMediumAttachmentData
33
 
{
34
 
    BackupableMediumAttachmentData()
35
 
        : lPort(0),
36
 
          lDevice(0),
37
 
          type(DeviceType_Null),
38
 
          fPassthrough(false),
39
 
          fImplicit(false)
40
 
    { }
41
 
 
42
 
    ComObjPtr<Medium>   pMedium;
43
 
    /* Since MediumAttachment is not a first class citizen when it
44
 
     * comes to managing settings, having a reference to the storage
45
 
     * controller will not work - when settings are changed it will point
46
 
     * to the old, uninitialized instance. Changing this requires
47
 
     * substantial changes to MediumImpl.cpp. */
48
 
    const Bstr          bstrControllerName;
49
 
    const LONG          lPort;
50
 
    const LONG          lDevice;
51
 
    const DeviceType_T  type;
52
 
    bool                fPassthrough : 1;
53
 
    bool                fImplicit : 1;
54
 
};
55
 
 
56
 
struct MediumAttachment::Data
57
 
{
58
 
    Data()
59
 
        : pMachine(NULL)
60
 
    { }
61
 
 
62
 
    /** Reference to Machine object, for checking mutable state. */
63
 
    Machine * const pMachine;
64
 
    /* later: const ComObjPtr<MediumAttachment> mPeer; */
65
 
 
66
 
    Backupable<BackupableMediumAttachmentData> bd;
67
 
};
68
 
 
69
 
// constructor / destructor
70
 
/////////////////////////////////////////////////////////////////////////////
71
 
 
72
 
HRESULT MediumAttachment::FinalConstruct()
73
 
{
74
 
    LogFlowThisFunc(("\n"));
75
 
    return S_OK;
76
 
}
77
 
 
78
 
void MediumAttachment::FinalRelease()
79
 
{
80
 
    LogFlowThisFuncEnter();
81
 
    uninit();
82
 
    LogFlowThisFuncLeave();
83
 
}
84
 
 
85
 
// public initializer/uninitializer for internal purposes only
86
 
/////////////////////////////////////////////////////////////////////////////
87
 
 
88
 
/**
89
 
 * Initializes the medium attachment object.
90
 
 *
91
 
 * @param aParent     Machine object.
92
 
 * @param aMedium     Medium object.
93
 
 * @param aController Controller the hard disk is attached to.
94
 
 * @param aPort       Port number.
95
 
 * @param aDevice     Device number on the port.
96
 
 * @param aPassthrough Wether accesses are directly passed to the host drive.
97
 
 */
98
 
HRESULT MediumAttachment::init(Machine *aParent,
99
 
                               Medium *aMedium,
100
 
                               const Bstr &aControllerName,
101
 
                               LONG aPort,
102
 
                               LONG aDevice,
103
 
                               DeviceType_T aType,
104
 
                               bool aPassthrough)
105
 
{
106
 
    LogFlowThisFuncEnter();
107
 
    LogFlowThisFunc(("aParent=%p aMedium=%p aControllerName=%ls aPort=%d aDevice=%d aType=%d aPassthrough=%d\n", aParent, aMedium, aControllerName.raw(), aPort, aDevice, aType, aPassthrough));
108
 
 
109
 
    if (aType == DeviceType_HardDisk)
110
 
        AssertReturn(aMedium, E_INVALIDARG);
111
 
 
112
 
    /* Enclose the state transition NotReady->InInit->Ready */
113
 
    AutoInitSpan autoInitSpan(this);
114
 
    AssertReturn(autoInitSpan.isOk(), E_FAIL);
115
 
 
116
 
    m = new Data();
117
 
 
118
 
    unconst(m->pMachine) = aParent;
119
 
 
120
 
    m->bd.allocate();
121
 
    m->bd->pMedium = aMedium;
122
 
    unconst(m->bd->bstrControllerName) = aControllerName;
123
 
    unconst(m->bd->lPort)   = aPort;
124
 
    unconst(m->bd->lDevice) = aDevice;
125
 
    unconst(m->bd->type)    = aType;
126
 
 
127
 
    m->bd->fPassthrough = aPassthrough;
128
 
    /* Newly created attachments never have an implicitly created medium
129
 
     * associated with them. Implicit diff image creation happens later. */
130
 
    m->bd->fImplicit = false;
131
 
 
132
 
    /* Confirm a successful initialization when it's the case */
133
 
    autoInitSpan.setSucceeded();
134
 
 
135
 
    /* Construct a short log name for this attachment. */
136
 
    Utf8Str ctlName(aControllerName);
137
 
    const char *psz = strpbrk(ctlName.c_str(), " \t:-");
138
 
    mLogName = Utf8StrFmt("MA%p[%.*s:%u:%u:%s%s]",
139
 
                          this,
140
 
                          psz ? psz - ctlName.c_str() : 4, ctlName.c_str(),
141
 
                          aPort, aDevice, Global::stringifyDeviceType(aType),
142
 
                          m->bd->fImplicit ? ":I" : "");
143
 
 
144
 
    LogFlowThisFunc(("LEAVE - %s\n", getLogName()));
145
 
    return S_OK;
146
 
}
147
 
 
148
 
/**
149
 
 * Uninitializes the instance.
150
 
 * Called from FinalRelease().
151
 
 */
152
 
void MediumAttachment::uninit()
153
 
{
154
 
    LogFlowThisFunc(("ENTER - %s\n", getLogName()));
155
 
 
156
 
    /* Enclose the state transition Ready->InUninit->NotReady */
157
 
    AutoUninitSpan autoUninitSpan(this);
158
 
    if (autoUninitSpan.uninitDone())
159
 
        return;
160
 
 
161
 
    m->bd.free();
162
 
 
163
 
    unconst(m->pMachine) = NULL;
164
 
 
165
 
    delete m;
166
 
    m = NULL;
167
 
 
168
 
    LogFlowThisFuncLeave();
169
 
}
170
 
 
171
 
// IHardDiskAttachment properties
172
 
/////////////////////////////////////////////////////////////////////////////
173
 
 
174
 
STDMETHODIMP MediumAttachment::COMGETTER(Medium)(IMedium **aHardDisk)
175
 
{
176
 
    LogFlowThisFuncEnter();
177
 
 
178
 
    CheckComArgOutPointerValid(aHardDisk);
179
 
 
180
 
    AutoCaller autoCaller(this);
181
 
    if (FAILED(autoCaller.rc())) return autoCaller.rc();
182
 
 
183
 
    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
184
 
 
185
 
    m->bd->pMedium.queryInterfaceTo(aHardDisk);
186
 
 
187
 
    LogFlowThisFuncLeave();
188
 
    return S_OK;
189
 
}
190
 
 
191
 
STDMETHODIMP MediumAttachment::COMGETTER(Controller)(BSTR *aController)
192
 
{
193
 
    LogFlowThisFuncEnter();
194
 
 
195
 
    CheckComArgOutPointerValid(aController);
196
 
 
197
 
    AutoCaller autoCaller(this);
198
 
    if (FAILED(autoCaller.rc())) return autoCaller.rc();
199
 
 
200
 
    /* m->controller is constant during life time, no need to lock */
201
 
    m->bd->bstrControllerName.cloneTo(aController);
202
 
 
203
 
    LogFlowThisFuncLeave();
204
 
    return S_OK;
205
 
}
206
 
 
207
 
STDMETHODIMP MediumAttachment::COMGETTER(Port)(LONG *aPort)
208
 
{
209
 
    LogFlowThisFuncEnter();
210
 
 
211
 
    CheckComArgOutPointerValid(aPort);
212
 
 
213
 
    AutoCaller autoCaller(this);
214
 
    if (FAILED(autoCaller.rc())) return autoCaller.rc();
215
 
 
216
 
    /* m->bd->port is constant during life time, no need to lock */
217
 
    *aPort = m->bd->lPort;
218
 
 
219
 
    LogFlowThisFuncLeave();
220
 
    return S_OK;
221
 
}
222
 
 
223
 
STDMETHODIMP MediumAttachment::COMGETTER(Device)(LONG *aDevice)
224
 
{
225
 
    LogFlowThisFuncEnter();
226
 
 
227
 
    CheckComArgOutPointerValid(aDevice);
228
 
 
229
 
    AutoCaller autoCaller(this);
230
 
    if (FAILED(autoCaller.rc())) return autoCaller.rc();
231
 
 
232
 
    /* m->bd->device is constant during life time, no need to lock */
233
 
    *aDevice = m->bd->lDevice;
234
 
 
235
 
    LogFlowThisFuncLeave();
236
 
    return S_OK;
237
 
}
238
 
 
239
 
STDMETHODIMP MediumAttachment::COMGETTER(Type)(DeviceType_T *aType)
240
 
{
241
 
    LogFlowThisFuncEnter();
242
 
 
243
 
    CheckComArgOutPointerValid(aType);
244
 
 
245
 
    AutoCaller autoCaller(this);
246
 
    if (FAILED(autoCaller.rc())) return autoCaller.rc();
247
 
 
248
 
    /* m->bd->type is constant during life time, no need to lock */
249
 
    *aType = m->bd->type;
250
 
 
251
 
    LogFlowThisFuncLeave();
252
 
    return S_OK;
253
 
}
254
 
 
255
 
STDMETHODIMP MediumAttachment::COMGETTER(Passthrough)(BOOL *aPassthrough)
256
 
{
257
 
    LogFlowThisFuncEnter();
258
 
 
259
 
    CheckComArgOutPointerValid(aPassthrough);
260
 
 
261
 
    AutoCaller autoCaller(this);
262
 
    if (FAILED(autoCaller.rc())) return autoCaller.rc();
263
 
 
264
 
    AutoReadLock lock(this COMMA_LOCKVAL_SRC_POS);
265
 
 
266
 
    *aPassthrough = m->bd->fPassthrough;
267
 
 
268
 
    LogFlowThisFuncLeave();
269
 
    return S_OK;
270
 
}
271
 
 
272
 
/**
273
 
 *  @note Locks this object for writing.
274
 
 */
275
 
void MediumAttachment::rollback()
276
 
{
277
 
    LogFlowThisFunc(("ENTER - %s\n", getLogName()));
278
 
 
279
 
    /* sanity */
280
 
    AutoCaller autoCaller(this);
281
 
    AssertComRCReturnVoid(autoCaller.rc());
282
 
 
283
 
    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
284
 
 
285
 
    m->bd.rollback();
286
 
 
287
 
    LogFlowThisFunc(("LEAVE - %s\n", getLogName()));
288
 
}
289
 
 
290
 
/**
291
 
 *  @note Locks this object for writing.
292
 
 */
293
 
void MediumAttachment::commit()
294
 
{
295
 
    LogFlowThisFuncEnter();
296
 
 
297
 
    /* sanity */
298
 
    AutoCaller autoCaller(this);
299
 
    AssertComRCReturnVoid (autoCaller.rc());
300
 
 
301
 
    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
302
 
 
303
 
    if (m->bd.isBackedUp())
304
 
        m->bd.commit();
305
 
 
306
 
    LogFlowThisFuncLeave();
307
 
}
308
 
 
309
 
bool MediumAttachment::isImplicit() const
310
 
{
311
 
    return m->bd->fImplicit;
312
 
}
313
 
 
314
 
void MediumAttachment::setImplicit(bool aImplicit)
315
 
{
316
 
    m->bd->fImplicit = aImplicit;
317
 
}
318
 
 
319
 
const ComObjPtr<Medium>& MediumAttachment::getMedium() const
320
 
{
321
 
    return m->bd->pMedium;
322
 
}
323
 
 
324
 
Bstr MediumAttachment::getControllerName() const
325
 
{
326
 
    return m->bd->bstrControllerName;
327
 
}
328
 
 
329
 
LONG MediumAttachment::getPort() const
330
 
{
331
 
    return m->bd->lPort;
332
 
}
333
 
 
334
 
LONG MediumAttachment::getDevice() const
335
 
{
336
 
    return m->bd->lDevice;
337
 
}
338
 
 
339
 
DeviceType_T MediumAttachment::getType() const
340
 
{
341
 
    return m->bd->type;
342
 
}
343
 
 
344
 
bool MediumAttachment::getPassthrough() const
345
 
{
346
 
    AutoReadLock lock(this COMMA_LOCKVAL_SRC_POS);
347
 
    return m->bd->fPassthrough;
348
 
}
349
 
 
350
 
bool MediumAttachment::matches(CBSTR aControllerName, LONG aPort, LONG aDevice)
351
 
{
352
 
    return (    aControllerName == m->bd->bstrControllerName
353
 
             && aPort == m->bd->lPort
354
 
             && aDevice == m->bd->lDevice);
355
 
}
356
 
 
357
 
/** Must be called from under this object's write lock. */
358
 
void MediumAttachment::updateMedium(const ComObjPtr<Medium> &aMedium)
359
 
{
360
 
    Assert(isWriteLockOnCurrentThread());
361
 
 
362
 
    m->bd.backup();
363
 
    m->bd->pMedium = aMedium;
364
 
}
365
 
 
366
 
/** Must be called from under this object's write lock. */
367
 
void MediumAttachment::updatePassthrough(bool aPassthrough)
368
 
{
369
 
    Assert(isWriteLockOnCurrentThread());
370
 
 
371
 
    m->bd.backup();
372
 
    m->bd->fPassthrough = aPassthrough;
373
 
}
374