VirtualBox

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

Last change on this file since 93410 was 93410, checked in by vboxsync, 3 years ago

Main: Generate enum value to string conversion functions for the API. Use these for logging instead of the Global::stringify* ones as they are untranslated, the Global:: ones are for use in error message when translated enum value names are desired (questionable).

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