VirtualBox

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

Last change on this file since 50403 was 49871, checked in by vboxsync, 11 years ago

6813 - User server side API wrapper code in all interfaces.. stage 4 rev 1

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 15.0 KB
Line 
1/** @file
2 *
3 * VirtualBox COM class implementation
4 */
5
6/*
7 * Copyright (C) 2006-2013 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 "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 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->getBandwidthGroup(m->bd->strBandwidthGroup, pBwGroup, true /* fSetError */);
368
369 Assert(SUCCEEDED(hrc)); /* This is not allowed to fail because the existence of the group was checked when it was attached. */
370
371 if (SUCCEEDED(hrc))
372 pBwGroup.queryInterfaceTo(aBandwidthGroup.asOutParam());
373 }
374
375 LogFlowThisFuncLeave();
376 return hrc;
377}
378
379HRESULT MediumAttachment::getHotPluggable(BOOL *aHotPluggable)
380{
381 LogFlowThisFuncEnter();
382
383 AutoReadLock lock(this COMMA_LOCKVAL_SRC_POS);
384
385 *aHotPluggable = m->bd->fHotPluggable;
386
387 LogFlowThisFuncLeave();
388 return S_OK;
389}
390
391/**
392 * @note Locks this object for writing.
393 */
394void MediumAttachment::i_rollback()
395{
396 LogFlowThisFunc(("ENTER - %s\n", i_getLogName()));
397
398 /* sanity */
399 AutoCaller autoCaller(this);
400 AssertComRCReturnVoid(autoCaller.rc());
401
402 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
403
404 m->bd.rollback();
405
406 LogFlowThisFunc(("LEAVE - %s\n", i_getLogName()));
407}
408
409/**
410 * @note Locks this object for writing.
411 */
412void MediumAttachment::i_commit()
413{
414 LogFlowThisFunc(("ENTER - %s\n", i_getLogName()));
415
416 /* sanity */
417 AutoCaller autoCaller(this);
418 AssertComRCReturnVoid (autoCaller.rc());
419
420 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
421
422 if (m->bd.isBackedUp())
423 m->bd.commit();
424
425 LogFlowThisFunc(("LEAVE - %s\n", i_getLogName()));
426}
427
428bool MediumAttachment::i_isImplicit() const
429{
430 return m->bd->fImplicit;
431}
432
433void MediumAttachment::i_setImplicit(bool aImplicit)
434{
435 m->bd->fImplicit = aImplicit;
436}
437
438const ComObjPtr<Medium>& MediumAttachment::i_getMedium() const
439{
440 return m->bd->pMedium;
441}
442
443const Bstr MediumAttachment::i_getControllerName() const
444{
445 return m->bd->bstrControllerName;
446}
447
448LONG MediumAttachment::i_getPort() const
449{
450 return m->bd->lPort;
451}
452
453LONG MediumAttachment::i_getDevice() const
454{
455 return m->bd->lDevice;
456}
457
458DeviceType_T MediumAttachment::i_getType() const
459{
460 return m->bd->type;
461}
462
463bool MediumAttachment::i_getPassthrough() const
464{
465 AutoReadLock lock(this COMMA_LOCKVAL_SRC_POS);
466 return m->bd->fPassthrough;
467}
468
469bool MediumAttachment::i_getTempEject() const
470{
471 AutoReadLock lock(this COMMA_LOCKVAL_SRC_POS);
472 return m->bd->fTempEject;
473}
474
475bool MediumAttachment::i_getNonRotational() const
476{
477 AutoReadLock lock(this COMMA_LOCKVAL_SRC_POS);
478 return m->bd->fNonRotational;
479}
480
481bool MediumAttachment::i_getDiscard() const
482{
483 AutoReadLock lock(this COMMA_LOCKVAL_SRC_POS);
484 return m->bd->fDiscard;
485}
486
487bool MediumAttachment::i_getHotPluggable() const
488{
489 AutoReadLock lock(this COMMA_LOCKVAL_SRC_POS);
490 return m->bd->fHotPluggable;
491}
492
493Utf8Str& MediumAttachment::i_getBandwidthGroup() const
494{
495 return m->bd->strBandwidthGroup;
496}
497
498bool MediumAttachment::i_matches(CBSTR aControllerName, LONG aPort, LONG aDevice)
499{
500 return ( aControllerName == m->bd->bstrControllerName
501 && aPort == m->bd->lPort
502 && aDevice == m->bd->lDevice);
503}
504
505/**
506 * Sets the medium of this attachment and unsets the "implicit" flag.
507 * @param aMedium
508 */
509void MediumAttachment::i_updateMedium(const ComObjPtr<Medium> &aMedium)
510{
511 Assert(isWriteLockOnCurrentThread());
512
513 m->bd.backup();
514 m->bd->pMedium = aMedium;
515 m->bd->fImplicit = false;
516 m->fIsEjected = false;
517}
518
519/** Must be called from under this object's write lock. */
520void MediumAttachment::i_updatePassthrough(bool aPassthrough)
521{
522 Assert(isWriteLockOnCurrentThread());
523
524 m->bd.backup();
525 m->bd->fPassthrough = aPassthrough;
526}
527
528/** Must be called from under this object's write lock. */
529void MediumAttachment::i_updateTempEject(bool aTempEject)
530{
531 Assert(isWriteLockOnCurrentThread());
532
533 m->bd.backup();
534 m->bd->fTempEject = aTempEject;
535}
536
537/** Must be called from under this object's write lock. */
538void MediumAttachment::i_updateEjected()
539{
540 Assert(isWriteLockOnCurrentThread());
541
542 m->fIsEjected = true;
543}
544
545/** Must be called from under this object's write lock. */
546void MediumAttachment::i_updateNonRotational(bool aNonRotational)
547{
548 Assert(isWriteLockOnCurrentThread());
549
550 m->bd.backup();
551 m->bd->fNonRotational = aNonRotational;
552}
553
554/** Must be called from under this object's write lock. */
555void MediumAttachment::i_updateDiscard(bool aDiscard)
556{
557 Assert(isWriteLockOnCurrentThread());
558
559 m->bd.backup();
560 m->bd->fDiscard = aDiscard;
561}
562
563/** Must be called from under this object's write lock. */
564void MediumAttachment::i_updateHotPluggable(bool aHotPluggable)
565{
566 Assert(isWriteLockOnCurrentThread());
567
568 m->bd.backup();
569 m->bd->fHotPluggable = aHotPluggable;
570}
571
572void MediumAttachment::i_updateBandwidthGroup(const Utf8Str &aBandwidthGroup)
573{
574 LogFlowThisFuncEnter();
575 Assert(isWriteLockOnCurrentThread());
576
577 m->bd.backup();
578 m->bd->strBandwidthGroup = aBandwidthGroup;
579
580 LogFlowThisFuncLeave();
581}
582
583void MediumAttachment::i_updateParentMachine(Machine * const pMachine)
584{
585 LogFlowThisFunc(("ENTER - %s\n", i_getLogName()));
586 /* sanity */
587 AutoCaller autoCaller(this);
588 AssertComRCReturnVoid (autoCaller.rc());
589
590 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
591
592 unconst(m->pMachine) = pMachine;
593
594 LogFlowThisFunc(("LEAVE - %s\n", i_getLogName()));
595}
596
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