VirtualBox

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

Last change on this file since 35479 was 35368, checked in by vboxsync, 14 years ago

Main: source re-org.

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