VirtualBox

source: vbox/trunk/src/VBox/Main/MediumAttachmentImpl.cpp@ 32876

Last change on this file since 32876 was 31301, checked in by vboxsync, 14 years ago

More resource control changes

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