VirtualBox

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

Last change on this file since 26167 was 26167, checked in by vboxsync, 15 years ago

Main: get rid of isModified() loops in Machine and subclasses; instead, on every change in machine settings, set dirty bits in Machine

File size: 10.4 KB
Line 
1/** @file
2 *
3 * VirtualBox COM class implementation
4 */
5
6/*
7 * Copyright (C) 2006-2009 Sun Microsystems, Inc.
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 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
18 * Clara, CA 95054 USA or visit http://www.sun.com if you need
19 * additional information or have any questions.
20 */
21
22#include "MediumAttachmentImpl.h"
23#include "MachineImpl.h"
24#include "MediumImpl.h"
25#include "Global.h"
26
27#include "AutoCaller.h"
28#include "Logging.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 bool operator==(const BackupableMediumAttachmentData &that) const
47 {
48 return this == &that
49 || (fPassthrough == that.fPassthrough);
50 }
51
52 ComObjPtr<Medium> pMedium;
53 /* Since MediumAttachment is not a first class citizen when it
54 * comes to managing settings, having a reference to the storage
55 * controller will not work - when settings are changed it will point
56 * to the old, uninitialized instance. Changing this requires
57 * substantial changes to MediumImpl.cpp. */
58 const Bstr bstrControllerName;
59 const LONG lPort;
60 const LONG lDevice;
61 const DeviceType_T type;
62 bool fPassthrough : 1;
63 bool fImplicit : 1;
64};
65
66struct MediumAttachment::Data
67{
68 Data()
69 { }
70
71 /** Reference to Machine object, for checking mutable state. */
72 const ComObjPtr<Machine, ComWeakRef> pMachine;
73 /* later: const ComObjPtr<MediumAttachment> mPeer; */
74
75 Backupable<BackupableMediumAttachmentData> bd;
76};
77
78// constructor / destructor
79/////////////////////////////////////////////////////////////////////////////
80
81HRESULT MediumAttachment::FinalConstruct()
82{
83 LogFlowThisFunc(("\n"));
84 return S_OK;
85}
86
87void MediumAttachment::FinalRelease()
88{
89 LogFlowThisFuncEnter();
90 uninit();
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 Wether accesses are directly passed to the host drive.
106 */
107HRESULT MediumAttachment::init(Machine *aParent,
108 Medium *aMedium,
109 const Bstr &aControllerName,
110 LONG aPort,
111 LONG aDevice,
112 DeviceType_T aType,
113 bool aPassthrough)
114{
115 LogFlowThisFuncEnter();
116 LogFlowThisFunc(("aParent=%p aMedium=%p aControllerName=%ls aPort=%d aDevice=%d aType=%d aPassthrough=%d\n", aParent, aMedium, aControllerName.raw(), aPort, aDevice, aType, aPassthrough));
117
118 if (aType == DeviceType_HardDisk)
119 AssertReturn(aMedium, E_INVALIDARG);
120
121 /* Enclose the state transition NotReady->InInit->Ready */
122 AutoInitSpan autoInitSpan(this);
123 AssertReturn(autoInitSpan.isOk(), E_FAIL);
124
125 m = new Data();
126
127 unconst(m->pMachine) = aParent;
128
129 m->bd.allocate();
130 m->bd->pMedium = aMedium;
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).setNull();
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
281/**
282 * @note Locks this object for writing.
283 */
284bool MediumAttachment::rollback()
285{
286 LogFlowThisFunc(("ENTER - %s\n", getLogName()));
287
288 /* sanity */
289 AutoCaller autoCaller(this);
290 AssertComRCReturn (autoCaller.rc(), false);
291
292 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
293
294 bool changed = false;
295
296 if (m->bd.isBackedUp())
297 {
298 /* we need to check all data to see whether anything will be changed
299 * after rollback */
300 changed = m->bd.hasActualChanges();
301 m->bd.rollback();
302 }
303
304 LogFlowThisFunc(("LEAVE - %s - returning %RTbool\n", getLogName(), changed));
305 return changed;
306}
307
308/**
309 * @note Locks this object for writing.
310 */
311void MediumAttachment::commit()
312{
313 LogFlowThisFuncEnter();
314
315 /* sanity */
316 AutoCaller autoCaller(this);
317 AssertComRCReturnVoid (autoCaller.rc());
318
319 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
320
321 if (m->bd.isBackedUp())
322 m->bd.commit();
323
324 LogFlowThisFuncLeave();
325}
326
327bool MediumAttachment::isImplicit() const
328{
329 return m->bd->fImplicit;
330}
331
332void MediumAttachment::setImplicit(bool aImplicit)
333{
334 m->bd->fImplicit = aImplicit;
335}
336
337const ComObjPtr<Medium>& MediumAttachment::getMedium() const
338{
339 return m->bd->pMedium;
340}
341
342Bstr MediumAttachment::getControllerName() const
343{
344 return m->bd->bstrControllerName;
345}
346
347LONG MediumAttachment::getPort() const
348{
349 return m->bd->lPort;
350}
351
352LONG MediumAttachment::getDevice() const
353{
354 return m->bd->lDevice;
355}
356
357DeviceType_T MediumAttachment::getType() const
358{
359 return m->bd->type;
360}
361
362bool MediumAttachment::getPassthrough() const
363{
364 AutoReadLock lock(this COMMA_LOCKVAL_SRC_POS);
365 return m->bd->fPassthrough;
366}
367
368bool MediumAttachment::matches(CBSTR aControllerName, LONG aPort, LONG aDevice)
369{
370 return ( aControllerName == m->bd->bstrControllerName
371 && aPort == m->bd->lPort
372 && aDevice == m->bd->lDevice);
373}
374
375/** Must be called from under this object's AND the machine's write lock. */
376void MediumAttachment::updateMedium(const ComObjPtr<Medium> &aMedium, bool aImplicit)
377{
378 Assert(m->pMachine->isWriteLockOnCurrentThread());
379 Assert(isWriteLockOnCurrentThread());
380
381 m->bd.backup();
382 m->bd->pMedium = aMedium;
383 m->bd->fImplicit = aImplicit;
384
385 m->pMachine->setModified(Machine::IsModified_Storage);
386}
387
388/** Must be called from under this object's AND the machine's write lock. */
389void MediumAttachment::updatePassthrough(bool aPassthrough)
390{
391 Assert(m->pMachine->isWriteLockOnCurrentThread());
392 Assert(isWriteLockOnCurrentThread());
393
394 m->bd.backup();
395 m->bd->fPassthrough = aPassthrough;
396
397 m->pMachine->setModified(Machine::IsModified_Storage);
398}
399
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