VirtualBox

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

Last change on this file since 36082 was 36059, checked in by vboxsync, 14 years ago

Main/BandwidthControl: Remove unused header

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