VirtualBox

source: vbox/trunk/src/VBox/Main/src-server/MediumAttachmentImpl.cpp@ 37704

Last change on this file since 37704 was 37695, checked in by vboxsync, 14 years ago

Main/MediumAttachment+Machine: maintain a flag whether the medium was ejected, and add a method to query this information

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 12.1 KB
Line 
1/** @file
2 *
3 * VirtualBox COM class implementation
4 */
5
6/*
7 * Copyright (C) 2006-2011 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 "AutoStateDep.h"
24#include "AutoCaller.h"
25#include "Logging.h"
26
27#include <iprt/cpp/utils.h>
28
29////////////////////////////////////////////////////////////////////////////////
30//
31// private member data definition
32//
33////////////////////////////////////////////////////////////////////////////////
34
35struct BackupableMediumAttachmentData
36{
37 BackupableMediumAttachmentData()
38 : lPort(0),
39 lDevice(0),
40 type(DeviceType_Null),
41 fPassthrough(false),
42 fImplicit(false)
43 { }
44
45 ComObjPtr<Medium> pMedium;
46 /* Since MediumAttachment is not a first class citizen when it
47 * comes to managing settings, having a reference to the storage
48 * controller will not work - when settings are changed it will point
49 * to the old, uninitialized instance. Changing this requires
50 * substantial changes to MediumImpl.cpp. */
51 const Bstr bstrControllerName;
52 /* Same counts for the assigned bandwidth group */
53 Utf8Str strBandwidthGroup;
54 const LONG lPort;
55 const LONG lDevice;
56 const DeviceType_T type;
57 bool fPassthrough;
58 bool fImplicit;
59};
60
61struct MediumAttachment::Data
62{
63 Data()
64 : pMachine(NULL),
65 fIsEjected(false)
66 { }
67
68 /** Reference to Machine object, for checking mutable state. */
69 Machine * const pMachine;
70 /* later: const ComObjPtr<MediumAttachment> mPeer; */
71
72 bool fIsEjected;
73
74 Backupable<BackupableMediumAttachmentData> bd;
75};
76
77// constructor / destructor
78/////////////////////////////////////////////////////////////////////////////
79
80HRESULT MediumAttachment::FinalConstruct()
81{
82 LogFlowThisFunc(("\n"));
83 return BaseFinalConstruct();
84}
85
86void MediumAttachment::FinalRelease()
87{
88 LogFlowThisFuncEnter();
89 uninit();
90 BaseFinalRelease();
91 LogFlowThisFuncLeave();
92}
93
94// public initializer/uninitializer for internal purposes only
95/////////////////////////////////////////////////////////////////////////////
96
97/**
98 * Initializes the medium attachment object.
99 *
100 * @param aParent Machine object.
101 * @param aMedium Medium object.
102 * @param aController Controller the hard disk is attached to.
103 * @param aPort Port number.
104 * @param aDevice Device number on the port.
105 * @param aPassthrough Whether accesses are directly passed to the host drive.
106 * @param aBandwidthLimit Bandwidth limit in Mbps
107 */
108HRESULT MediumAttachment::init(Machine *aParent,
109 Medium *aMedium,
110 const Bstr &aControllerName,
111 LONG aPort,
112 LONG aDevice,
113 DeviceType_T aType,
114 bool aPassthrough,
115 const Utf8Str &strBandwidthGroup)
116{
117 LogFlowThisFuncEnter();
118 LogFlowThisFunc(("aParent=%p aMedium=%p aControllerName=%ls aPort=%d aDevice=%d aType=%d aPassthrough=%d\n", aParent, aMedium, aControllerName.raw(), aPort, aDevice, aType, aPassthrough));
119
120 if (aType == DeviceType_HardDisk)
121 AssertReturn(aMedium, E_INVALIDARG);
122
123 /* Enclose the state transition NotReady->InInit->Ready */
124 AutoInitSpan autoInitSpan(this);
125 AssertReturn(autoInitSpan.isOk(), E_FAIL);
126
127 m = new Data();
128
129 unconst(m->pMachine) = aParent;
130
131 m->bd.allocate();
132 m->bd->pMedium = aMedium;
133 unconst(m->bd->strBandwidthGroup) = strBandwidthGroup;
134 unconst(m->bd->bstrControllerName) = aControllerName;
135 unconst(m->bd->lPort) = aPort;
136 unconst(m->bd->lDevice) = aDevice;
137 unconst(m->bd->type) = aType;
138
139 m->bd->fPassthrough = aPassthrough;
140 /* Newly created attachments never have an implicitly created medium
141 * associated with them. Implicit diff image creation happens later. */
142 m->bd->fImplicit = false;
143
144 /* Confirm a successful initialization when it's the case */
145 autoInitSpan.setSucceeded();
146
147 /* Construct a short log name for this attachment. */
148 Utf8Str ctlName(aControllerName);
149 const char *psz = strpbrk(ctlName.c_str(), " \t:-");
150 mLogName = Utf8StrFmt("MA%p[%.*s:%u:%u:%s%s]",
151 this,
152 psz ? psz - ctlName.c_str() : 4, ctlName.c_str(),
153 aPort, aDevice, Global::stringifyDeviceType(aType),
154 m->bd->fImplicit ? ":I" : "");
155
156 LogFlowThisFunc(("LEAVE - %s\n", getLogName()));
157 return S_OK;
158}
159
160/**
161 * Uninitializes the instance.
162 * Called from FinalRelease().
163 */
164void MediumAttachment::uninit()
165{
166 LogFlowThisFunc(("ENTER - %s\n", getLogName()));
167
168 /* Enclose the state transition Ready->InUninit->NotReady */
169 AutoUninitSpan autoUninitSpan(this);
170 if (autoUninitSpan.uninitDone())
171 return;
172
173 m->bd.free();
174
175 unconst(m->pMachine) = NULL;
176
177 delete m;
178 m = NULL;
179
180 LogFlowThisFuncLeave();
181}
182
183// IHardDiskAttachment properties
184/////////////////////////////////////////////////////////////////////////////
185
186STDMETHODIMP MediumAttachment::COMGETTER(Medium)(IMedium **aHardDisk)
187{
188 LogFlowThisFuncEnter();
189
190 CheckComArgOutPointerValid(aHardDisk);
191
192 AutoCaller autoCaller(this);
193 if (FAILED(autoCaller.rc())) return autoCaller.rc();
194
195 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
196
197 m->bd->pMedium.queryInterfaceTo(aHardDisk);
198
199 LogFlowThisFuncLeave();
200 return S_OK;
201}
202
203STDMETHODIMP MediumAttachment::COMGETTER(Controller)(BSTR *aController)
204{
205 LogFlowThisFuncEnter();
206
207 CheckComArgOutPointerValid(aController);
208
209 AutoCaller autoCaller(this);
210 if (FAILED(autoCaller.rc())) return autoCaller.rc();
211
212 /* m->controller is constant during life time, no need to lock */
213 m->bd->bstrControllerName.cloneTo(aController);
214
215 LogFlowThisFuncLeave();
216 return S_OK;
217}
218
219STDMETHODIMP MediumAttachment::COMGETTER(Port)(LONG *aPort)
220{
221 LogFlowThisFuncEnter();
222
223 CheckComArgOutPointerValid(aPort);
224
225 AutoCaller autoCaller(this);
226 if (FAILED(autoCaller.rc())) return autoCaller.rc();
227
228 /* m->bd->port is constant during life time, no need to lock */
229 *aPort = m->bd->lPort;
230
231 LogFlowThisFuncLeave();
232 return S_OK;
233}
234
235STDMETHODIMP MediumAttachment::COMGETTER(Device)(LONG *aDevice)
236{
237 LogFlowThisFuncEnter();
238
239 CheckComArgOutPointerValid(aDevice);
240
241 AutoCaller autoCaller(this);
242 if (FAILED(autoCaller.rc())) return autoCaller.rc();
243
244 /* m->bd->device is constant during life time, no need to lock */
245 *aDevice = m->bd->lDevice;
246
247 LogFlowThisFuncLeave();
248 return S_OK;
249}
250
251STDMETHODIMP MediumAttachment::COMGETTER(Type)(DeviceType_T *aType)
252{
253 LogFlowThisFuncEnter();
254
255 CheckComArgOutPointerValid(aType);
256
257 AutoCaller autoCaller(this);
258 if (FAILED(autoCaller.rc())) return autoCaller.rc();
259
260 /* m->bd->type is constant during life time, no need to lock */
261 *aType = m->bd->type;
262
263 LogFlowThisFuncLeave();
264 return S_OK;
265}
266
267STDMETHODIMP MediumAttachment::COMGETTER(Passthrough)(BOOL *aPassthrough)
268{
269 LogFlowThisFuncEnter();
270
271 CheckComArgOutPointerValid(aPassthrough);
272
273 AutoCaller autoCaller(this);
274 if (FAILED(autoCaller.rc())) return autoCaller.rc();
275
276 AutoReadLock lock(this COMMA_LOCKVAL_SRC_POS);
277
278 *aPassthrough = m->bd->fPassthrough;
279
280 LogFlowThisFuncLeave();
281 return S_OK;
282}
283
284STDMETHODIMP MediumAttachment::COMGETTER(IsEjected)(BOOL *aEjected)
285{
286 LogFlowThisFuncEnter();
287
288 CheckComArgOutPointerValid(aEjected);
289
290 AutoCaller autoCaller(this);
291 if (FAILED(autoCaller.rc())) return autoCaller.rc();
292
293 AutoReadLock lock(this COMMA_LOCKVAL_SRC_POS);
294
295 *aEjected = m->fIsEjected;
296
297 LogFlowThisFuncLeave();
298 return S_OK;
299}
300
301STDMETHODIMP MediumAttachment::COMGETTER(BandwidthGroup) (IBandwidthGroup **aBwGroup)
302{
303 LogFlowThisFuncEnter();
304 CheckComArgOutPointerValid(aBwGroup);
305
306 AutoCaller autoCaller(this);
307 if (FAILED(autoCaller.rc())) return autoCaller.rc();
308
309 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
310
311 HRESULT hrc = S_OK;
312 if (m->bd->strBandwidthGroup.isNotEmpty())
313 {
314 ComObjPtr<BandwidthGroup> pBwGroup;
315 hrc = m->pMachine->getBandwidthGroup(m->bd->strBandwidthGroup, pBwGroup, true /* fSetError */);
316
317 Assert(SUCCEEDED(hrc)); /* This is not allowed to fail because the existence of the group was checked when it was attached. */
318
319 if (SUCCEEDED(hrc))
320 pBwGroup.queryInterfaceTo(aBwGroup);
321 }
322
323 LogFlowThisFuncLeave();
324 return hrc;
325}
326
327/**
328 * @note Locks this object for writing.
329 */
330void MediumAttachment::rollback()
331{
332 LogFlowThisFunc(("ENTER - %s\n", getLogName()));
333
334 /* sanity */
335 AutoCaller autoCaller(this);
336 AssertComRCReturnVoid(autoCaller.rc());
337
338 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
339
340 m->bd.rollback();
341
342 LogFlowThisFunc(("LEAVE - %s\n", getLogName()));
343}
344
345/**
346 * @note Locks this object for writing.
347 */
348void MediumAttachment::commit()
349{
350 LogFlowThisFunc(("ENTER - %s\n", getLogName()));
351
352 /* sanity */
353 AutoCaller autoCaller(this);
354 AssertComRCReturnVoid (autoCaller.rc());
355
356 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
357
358 if (m->bd.isBackedUp())
359 m->bd.commit();
360
361 LogFlowThisFunc(("LEAVE - %s\n", getLogName()));
362}
363
364bool MediumAttachment::isImplicit() const
365{
366 return m->bd->fImplicit;
367}
368
369void MediumAttachment::setImplicit(bool aImplicit)
370{
371 m->bd->fImplicit = aImplicit;
372}
373
374const ComObjPtr<Medium>& MediumAttachment::getMedium() const
375{
376 return m->bd->pMedium;
377}
378
379Bstr MediumAttachment::getControllerName() const
380{
381 return m->bd->bstrControllerName;
382}
383
384LONG MediumAttachment::getPort() const
385{
386 return m->bd->lPort;
387}
388
389LONG MediumAttachment::getDevice() const
390{
391 return m->bd->lDevice;
392}
393
394DeviceType_T MediumAttachment::getType() const
395{
396 return m->bd->type;
397}
398
399bool MediumAttachment::getPassthrough() const
400{
401 AutoReadLock lock(this COMMA_LOCKVAL_SRC_POS);
402 return m->bd->fPassthrough;
403}
404
405const Utf8Str& MediumAttachment::getBandwidthGroup() const
406{
407 return m->bd->strBandwidthGroup;
408}
409
410bool MediumAttachment::matches(CBSTR aControllerName, LONG aPort, LONG aDevice)
411{
412 return ( aControllerName == m->bd->bstrControllerName
413 && aPort == m->bd->lPort
414 && aDevice == m->bd->lDevice);
415}
416
417/**
418 * Sets the medium of this attachment and unsets the "implicit" flag.
419 * @param aMedium
420 */
421void MediumAttachment::updateMedium(const ComObjPtr<Medium> &aMedium)
422{
423 Assert(isWriteLockOnCurrentThread());
424
425 m->bd.backup();
426 m->bd->pMedium = aMedium;
427 m->bd->fImplicit = false;
428 m->fIsEjected = false;
429}
430
431/** Must be called from under this object's write lock. */
432void MediumAttachment::updatePassthrough(bool aPassthrough)
433{
434 Assert(isWriteLockOnCurrentThread());
435
436 m->bd.backup();
437 m->bd->fPassthrough = aPassthrough;
438}
439
440/** Must be called from under this object's write lock. */
441void MediumAttachment::updateEjected()
442{
443 Assert(isWriteLockOnCurrentThread());
444
445 m->fIsEjected = true;
446}
447
448void MediumAttachment::updateBandwidthGroup(const Utf8Str &aBandwidthGroup)
449{
450 LogFlowThisFuncEnter();
451 Assert(isWriteLockOnCurrentThread());
452
453 m->bd.backup();
454 m->bd->strBandwidthGroup = aBandwidthGroup;
455
456 LogFlowThisFuncLeave();
457}
458
459void MediumAttachment::updateParentMachine(Machine * const pMachine)
460{
461 LogFlowThisFunc(("ENTER - %s\n", getLogName()));
462
463 /* sanity */
464 AutoCaller autoCaller(this);
465 AssertComRCReturnVoid (autoCaller.rc());
466
467 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
468
469 unconst(m->pMachine) = pMachine;
470
471 LogFlowThisFunc(("LEAVE - %s\n", getLogName()));
472}
473
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