VirtualBox

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

Last change on this file since 35814 was 35638, checked in by vboxsync, 14 years ago

Main. QT/FE: fix long standing COM issue

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