VirtualBox

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

Last change on this file since 56574 was 55401, checked in by vboxsync, 10 years ago

added a couple of missing Id headers

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 15.0 KB
Line 
1/* $Id: MediumAttachmentImpl.cpp 55401 2015-04-23 10:03:17Z vboxsync $ */
2/** @file
3 *
4 * VirtualBox COM class implementation
5 */
6
7/*
8 * Copyright (C) 2006-2015 Oracle Corporation
9 *
10 * This file is part of VirtualBox Open Source Edition (OSE), as
11 * available from http://www.virtualbox.org. This file is free software;
12 * you can redistribute it and/or modify it under the terms of the GNU
13 * General Public License (GPL) as published by the Free Software
14 * Foundation, in version 2 as it comes in the "COPYING" file of the
15 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
16 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
17 */
18
19#include "MediumAttachmentImpl.h"
20#include "MachineImpl.h"
21#include "MediumImpl.h"
22#include "Global.h"
23
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 fTempEject(false),
43 fNonRotational(false),
44 fDiscard(false),
45 fImplicit(false),
46 fHotPluggable(false)
47 { }
48
49 ComObjPtr<Medium> pMedium;
50 /* Since MediumAttachment is not a first class citizen when it
51 * comes to managing settings, having a reference to the storage
52 * controller will not work - when settings are changed it will point
53 * to the old, uninitialized instance. Changing this requires
54 * substantial changes to MediumImpl.cpp. */
55 const Bstr bstrControllerName;
56 /* Same counts for the assigned bandwidth group */
57 Utf8Str strBandwidthGroup;
58 const LONG lPort;
59 const LONG lDevice;
60 const DeviceType_T type;
61 bool fPassthrough;
62 bool fTempEject;
63 bool fNonRotational;
64 bool fDiscard;
65 bool fImplicit;
66 bool fHotPluggable;
67};
68
69struct MediumAttachment::Data
70{
71 Data(Machine * const aMachine = NULL)
72 : pMachine(aMachine),
73 fIsEjected(false)
74 { }
75
76 /** Reference to Machine object, for checking mutable state. */
77 Machine * const pMachine;
78 /* later: const ComObjPtr<MediumAttachment> mPeer; */
79
80 bool fIsEjected;
81
82 Backupable<BackupableMediumAttachmentData> bd;
83};
84
85// constructor / destructor
86/////////////////////////////////////////////////////////////////////////////
87
88DEFINE_EMPTY_CTOR_DTOR(MediumAttachment)
89
90HRESULT MediumAttachment::FinalConstruct()
91{
92 LogFlowThisFunc(("\n"));
93 return BaseFinalConstruct();
94}
95
96void MediumAttachment::FinalRelease()
97{
98 LogFlowThisFuncEnter();
99 uninit();
100 BaseFinalRelease();
101 LogFlowThisFuncLeave();
102}
103
104// public initializer/uninitializer for internal purposes only
105/////////////////////////////////////////////////////////////////////////////
106
107/**
108 * Initializes the medium attachment object.
109 *
110 * @param aParent Machine object.
111 * @param aMedium Medium object.
112 * @param aController Controller the hard disk is attached to.
113 * @param aPort Port number.
114 * @param aDevice Device number on the port.
115 * @param aPassthrough Whether accesses are directly passed to the host drive.
116 * @param aBandwidthLimit Bandwidth limit in Mbps
117 */
118HRESULT MediumAttachment::init(Machine *aParent,
119 Medium *aMedium,
120 const Bstr &aControllerName,
121 LONG aPort,
122 LONG aDevice,
123 DeviceType_T aType,
124 bool aImplicit,
125 bool aPassthrough,
126 bool aTempEject,
127 bool aNonRotational,
128 bool aDiscard,
129 bool aHotPluggable,
130 const Utf8Str &strBandwidthGroup)
131{
132 LogFlowThisFuncEnter();
133 LogFlowThisFunc(("aParent=%p aMedium=%p aControllerName=%ls aPort=%d aDevice=%d aType=%d aImplicit=%d aPassthrough=%d aTempEject=%d aNonRotational=%d aDiscard=%d aHotPluggable=%d strBandwithGroup=%s\n", aParent, aMedium, aControllerName.raw(), aPort, aDevice, aType, aImplicit, aPassthrough, aTempEject, aNonRotational, aDiscard, aHotPluggable, strBandwidthGroup.c_str()));
134
135 if (aType == DeviceType_HardDisk)
136 AssertReturn(aMedium, E_INVALIDARG);
137
138 /* Enclose the state transition NotReady->InInit->Ready */
139 AutoInitSpan autoInitSpan(this);
140 AssertReturn(autoInitSpan.isOk(), E_FAIL);
141
142 m = new Data();
143
144 unconst(m->pMachine) = aParent;
145
146 m->bd.allocate();
147 m->bd->pMedium = aMedium;
148 unconst(m->bd->strBandwidthGroup) = strBandwidthGroup;
149 unconst(m->bd->bstrControllerName) = aControllerName;
150 unconst(m->bd->lPort) = aPort;
151 unconst(m->bd->lDevice) = aDevice;
152 unconst(m->bd->type) = aType;
153
154 m->bd->fPassthrough = aPassthrough;
155 m->bd->fTempEject = aTempEject;
156 m->bd->fNonRotational = aNonRotational;
157 m->bd->fDiscard = aDiscard;
158 m->bd->fImplicit = aImplicit;
159 m->bd->fHotPluggable = aHotPluggable;
160
161 /* Confirm a successful initialization when it's the case */
162 autoInitSpan.setSucceeded();
163
164 /* Construct a short log name for this attachment. */
165 Utf8Str ctlName(aControllerName);
166 const char *psz = strpbrk(ctlName.c_str(), " \t:-");
167 mLogName = Utf8StrFmt("MA%p[%.*s:%u:%u:%s%s]",
168 this,
169 psz ? psz - ctlName.c_str() : 4, ctlName.c_str(),
170 aPort, aDevice, Global::stringifyDeviceType(aType),
171 m->bd->fImplicit ? ":I" : "");
172
173 LogFlowThisFunc(("LEAVE - %s\n", i_getLogName()));
174 return S_OK;
175}
176
177/**
178 * Initializes the medium attachment object given another guest object
179 * (a kind of copy constructor). This object makes a private copy of data
180 * of the original object passed as an argument.
181 */
182HRESULT MediumAttachment::initCopy(Machine *aParent, MediumAttachment *aThat)
183{
184 LogFlowThisFunc(("aParent=%p, aThat=%p\n", aParent, aThat));
185
186 ComAssertRet(aParent && aThat, E_INVALIDARG);
187
188 /* Enclose the state transition NotReady->InInit->Ready */
189 AutoInitSpan autoInitSpan(this);
190 AssertReturn(autoInitSpan.isOk(), E_FAIL);
191
192 m = new Data(aParent);
193 /* m->pPeer is left null */
194
195 AutoCaller thatCaller(aThat);
196 AssertComRCReturnRC(thatCaller.rc());
197
198 AutoReadLock thatlock(aThat COMMA_LOCKVAL_SRC_POS);
199 m->bd.attachCopy(aThat->m->bd);
200
201 /* Confirm a successful initialization */
202 autoInitSpan.setSucceeded();
203
204 return S_OK;
205}
206
207/**
208 * Uninitializes the instance.
209 * Called from FinalRelease().
210 */
211void MediumAttachment::uninit()
212{
213 LogFlowThisFunc(("ENTER - %s\n", i_getLogName()));
214
215 /* Enclose the state transition Ready->InUninit->NotReady */
216 AutoUninitSpan autoUninitSpan(this);
217 if (autoUninitSpan.uninitDone())
218 return;
219
220 m->bd.free();
221
222 unconst(m->pMachine) = NULL;
223
224 delete m;
225 m = NULL;
226
227 LogFlowThisFuncLeave();
228}
229
230// IHardDiskAttachment properties
231/////////////////////////////////////////////////////////////////////////////
232
233
234HRESULT MediumAttachment::getMedium(ComPtr<IMedium> &aHardDisk)
235{
236 LogFlowThisFuncEnter();
237
238 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
239
240 aHardDisk = m->bd->pMedium;
241
242 LogFlowThisFuncLeave();
243 return S_OK;
244}
245
246
247HRESULT MediumAttachment::getController(com::Utf8Str &aController)
248{
249 LogFlowThisFuncEnter();
250
251 /* m->controller is constant during life time, no need to lock */
252 aController = Utf8Str(m->bd->bstrControllerName);
253
254 LogFlowThisFuncLeave();
255 return S_OK;
256}
257
258
259HRESULT MediumAttachment::getPort(LONG *aPort)
260{
261 LogFlowThisFuncEnter();
262
263 /* m->bd->port is constant during life time, no need to lock */
264 *aPort = m->bd->lPort;
265
266 LogFlowThisFuncLeave();
267 return S_OK;
268}
269
270HRESULT MediumAttachment::getDevice(LONG *aDevice)
271{
272 LogFlowThisFuncEnter();
273
274 /* m->bd->device is constant during life time, no need to lock */
275 *aDevice = m->bd->lDevice;
276
277 LogFlowThisFuncLeave();
278 return S_OK;
279}
280
281HRESULT MediumAttachment::getType(DeviceType_T *aType)
282{
283 LogFlowThisFuncEnter();
284
285 /* m->bd->type is constant during life time, no need to lock */
286 *aType = m->bd->type;
287
288 LogFlowThisFuncLeave();
289 return S_OK;
290}
291
292
293HRESULT MediumAttachment::getPassthrough(BOOL *aPassthrough)
294{
295 LogFlowThisFuncEnter();
296
297 AutoReadLock lock(this COMMA_LOCKVAL_SRC_POS);
298
299 *aPassthrough = m->bd->fPassthrough;
300
301 LogFlowThisFuncLeave();
302 return S_OK;
303}
304
305
306HRESULT MediumAttachment::getTemporaryEject(BOOL *aTemporaryEject)
307{
308 LogFlowThisFuncEnter();
309
310 AutoReadLock lock(this COMMA_LOCKVAL_SRC_POS);
311
312 *aTemporaryEject = m->bd->fTempEject;
313
314 LogFlowThisFuncLeave();
315 return S_OK;
316}
317
318
319HRESULT MediumAttachment::getIsEjected(BOOL *aEjected)
320{
321 LogFlowThisFuncEnter();
322
323 AutoReadLock lock(this COMMA_LOCKVAL_SRC_POS);
324
325 *aEjected = m->fIsEjected;
326
327 LogFlowThisFuncLeave();
328 return S_OK;
329}
330
331
332HRESULT MediumAttachment::getNonRotational(BOOL *aNonRotational)
333{
334 LogFlowThisFuncEnter();
335
336 AutoReadLock lock(this COMMA_LOCKVAL_SRC_POS);
337
338 *aNonRotational = m->bd->fNonRotational;
339
340 LogFlowThisFuncLeave();
341 return S_OK;
342}
343
344HRESULT MediumAttachment::getDiscard(BOOL *aDiscard)
345{
346 LogFlowThisFuncEnter();
347
348 AutoReadLock lock(this COMMA_LOCKVAL_SRC_POS);
349
350 *aDiscard = m->bd->fDiscard;
351
352 LogFlowThisFuncLeave();
353 return S_OK;
354}
355
356
357HRESULT MediumAttachment::getBandwidthGroup(ComPtr<IBandwidthGroup> &aBandwidthGroup)
358{
359 LogFlowThisFuncEnter();
360
361 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
362
363 HRESULT hrc = S_OK;
364 if (m->bd->strBandwidthGroup.isNotEmpty())
365 {
366 ComObjPtr<BandwidthGroup> pBwGroup;
367 hrc = m->pMachine->i_getBandwidthGroup(m->bd->strBandwidthGroup, pBwGroup, true /* fSetError */);
368
369 Assert(SUCCEEDED(hrc)); /* This is not allowed to fail because the existence of the
370 group was checked when it was attached. */
371
372 if (SUCCEEDED(hrc))
373 pBwGroup.queryInterfaceTo(aBandwidthGroup.asOutParam());
374 }
375
376 LogFlowThisFuncLeave();
377 return hrc;
378}
379
380HRESULT MediumAttachment::getHotPluggable(BOOL *aHotPluggable)
381{
382 LogFlowThisFuncEnter();
383
384 AutoReadLock lock(this COMMA_LOCKVAL_SRC_POS);
385
386 *aHotPluggable = m->bd->fHotPluggable;
387
388 LogFlowThisFuncLeave();
389 return S_OK;
390}
391
392/**
393 * @note Locks this object for writing.
394 */
395void MediumAttachment::i_rollback()
396{
397 LogFlowThisFunc(("ENTER - %s\n", i_getLogName()));
398
399 /* sanity */
400 AutoCaller autoCaller(this);
401 AssertComRCReturnVoid(autoCaller.rc());
402
403 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
404
405 m->bd.rollback();
406
407 LogFlowThisFunc(("LEAVE - %s\n", i_getLogName()));
408}
409
410/**
411 * @note Locks this object for writing.
412 */
413void MediumAttachment::i_commit()
414{
415 LogFlowThisFunc(("ENTER - %s\n", i_getLogName()));
416
417 /* sanity */
418 AutoCaller autoCaller(this);
419 AssertComRCReturnVoid (autoCaller.rc());
420
421 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
422
423 if (m->bd.isBackedUp())
424 m->bd.commit();
425
426 LogFlowThisFunc(("LEAVE - %s\n", i_getLogName()));
427}
428
429bool MediumAttachment::i_isImplicit() const
430{
431 return m->bd->fImplicit;
432}
433
434void MediumAttachment::i_setImplicit(bool aImplicit)
435{
436 m->bd->fImplicit = aImplicit;
437}
438
439const ComObjPtr<Medium>& MediumAttachment::i_getMedium() const
440{
441 return m->bd->pMedium;
442}
443
444const Bstr MediumAttachment::i_getControllerName() const
445{
446 return m->bd->bstrControllerName;
447}
448
449LONG MediumAttachment::i_getPort() const
450{
451 return m->bd->lPort;
452}
453
454LONG MediumAttachment::i_getDevice() const
455{
456 return m->bd->lDevice;
457}
458
459DeviceType_T MediumAttachment::i_getType() const
460{
461 return m->bd->type;
462}
463
464bool MediumAttachment::i_getPassthrough() const
465{
466 AutoReadLock lock(this COMMA_LOCKVAL_SRC_POS);
467 return m->bd->fPassthrough;
468}
469
470bool MediumAttachment::i_getTempEject() const
471{
472 AutoReadLock lock(this COMMA_LOCKVAL_SRC_POS);
473 return m->bd->fTempEject;
474}
475
476bool MediumAttachment::i_getNonRotational() const
477{
478 AutoReadLock lock(this COMMA_LOCKVAL_SRC_POS);
479 return m->bd->fNonRotational;
480}
481
482bool MediumAttachment::i_getDiscard() const
483{
484 AutoReadLock lock(this COMMA_LOCKVAL_SRC_POS);
485 return m->bd->fDiscard;
486}
487
488bool MediumAttachment::i_getHotPluggable() const
489{
490 AutoReadLock lock(this COMMA_LOCKVAL_SRC_POS);
491 return m->bd->fHotPluggable;
492}
493
494Utf8Str& MediumAttachment::i_getBandwidthGroup() const
495{
496 return m->bd->strBandwidthGroup;
497}
498
499bool MediumAttachment::i_matches(CBSTR aControllerName, LONG aPort, LONG aDevice)
500{
501 return ( aControllerName == m->bd->bstrControllerName
502 && aPort == m->bd->lPort
503 && aDevice == m->bd->lDevice);
504}
505
506/**
507 * Sets the medium of this attachment and unsets the "implicit" flag.
508 * @param aMedium
509 */
510void MediumAttachment::i_updateMedium(const ComObjPtr<Medium> &aMedium)
511{
512 Assert(isWriteLockOnCurrentThread());
513
514 m->bd.backup();
515 m->bd->pMedium = aMedium;
516 m->bd->fImplicit = false;
517 m->fIsEjected = false;
518}
519
520/** Must be called from under this object's write lock. */
521void MediumAttachment::i_updatePassthrough(bool aPassthrough)
522{
523 Assert(isWriteLockOnCurrentThread());
524
525 m->bd.backup();
526 m->bd->fPassthrough = aPassthrough;
527}
528
529/** Must be called from under this object's write lock. */
530void MediumAttachment::i_updateTempEject(bool aTempEject)
531{
532 Assert(isWriteLockOnCurrentThread());
533
534 m->bd.backup();
535 m->bd->fTempEject = aTempEject;
536}
537
538/** Must be called from under this object's write lock. */
539void MediumAttachment::i_updateEjected()
540{
541 Assert(isWriteLockOnCurrentThread());
542
543 m->fIsEjected = true;
544}
545
546/** Must be called from under this object's write lock. */
547void MediumAttachment::i_updateNonRotational(bool aNonRotational)
548{
549 Assert(isWriteLockOnCurrentThread());
550
551 m->bd.backup();
552 m->bd->fNonRotational = aNonRotational;
553}
554
555/** Must be called from under this object's write lock. */
556void MediumAttachment::i_updateDiscard(bool aDiscard)
557{
558 Assert(isWriteLockOnCurrentThread());
559
560 m->bd.backup();
561 m->bd->fDiscard = aDiscard;
562}
563
564/** Must be called from under this object's write lock. */
565void MediumAttachment::i_updateHotPluggable(bool aHotPluggable)
566{
567 Assert(isWriteLockOnCurrentThread());
568
569 m->bd.backup();
570 m->bd->fHotPluggable = aHotPluggable;
571}
572
573void MediumAttachment::i_updateBandwidthGroup(const Utf8Str &aBandwidthGroup)
574{
575 LogFlowThisFuncEnter();
576 Assert(isWriteLockOnCurrentThread());
577
578 m->bd.backup();
579 m->bd->strBandwidthGroup = aBandwidthGroup;
580
581 LogFlowThisFuncLeave();
582}
583
584void MediumAttachment::i_updateParentMachine(Machine * const pMachine)
585{
586 LogFlowThisFunc(("ENTER - %s\n", i_getLogName()));
587 /* sanity */
588 AutoCaller autoCaller(this);
589 AssertComRCReturnVoid (autoCaller.rc());
590
591 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
592
593 unconst(m->pMachine) = pMachine;
594
595 LogFlowThisFunc(("LEAVE - %s\n", i_getLogName()));
596}
597
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