VirtualBox

source: vbox/trunk/src/VBox/Main/StorageControllerImpl.cpp@ 25414

Last change on this file since 25414 was 25346, checked in by vboxsync, 14 years ago

iprt/cpputils.h -> iprt/cpp/utils.h

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 21.9 KB
RevLine 
[17768]1/* $Id: StorageControllerImpl.cpp 25346 2009-12-13 16:21:19Z vboxsync $ */
2
3/** @file
4 *
5 * Implementation of IStorageController.
6 */
7
8/*
[23223]9 * Copyright (C) 2008-2009 Sun Microsystems, Inc.
[17768]10 *
11 * This file is part of VirtualBox Open Source Edition (OSE), as
12 * available from http://www.virtualbox.org. This file is free software;
13 * you can redistribute it and/or modify it under the terms of the GNU
14 * General Public License (GPL) as published by the Free Software
15 * Foundation, in version 2 as it comes in the "COPYING" file of the
16 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
17 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
18 *
19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
20 * Clara, CA 95054 USA or visit http://www.sun.com if you need
21 * additional information or have any questions.
22 */
23
24#include "StorageControllerImpl.h"
25#include "MachineImpl.h"
26#include "VirtualBoxImpl.h"
27#include "Logging.h"
28
29#include <iprt/string.h>
[25346]30#include <iprt/cpp/utils.h>
[17768]31
32#include <VBox/err.h>
33#include <VBox/settings.h>
34
35#include <algorithm>
36
37// defines
38/////////////////////////////////////////////////////////////////////////////
39
[25198]40struct BackupableStorageControllerData
41{
42 /* Constructor. */
43 BackupableStorageControllerData()
44 : mStorageBus(StorageBus_IDE),
45 mStorageControllerType(StorageControllerType_PIIX4),
46 mInstance(0),
47 mPortCount(2),
48 mPortIde0Master(0),
49 mPortIde0Slave(1),
50 mPortIde1Master(2),
51 mPortIde1Slave(3)
52 { }
53
54 bool operator==(const BackupableStorageControllerData &that) const
55 {
56 return this == &that
57 || ( (mStorageControllerType == that.mStorageControllerType)
58 && (strName == that.strName)
59 && (mPortCount == that.mPortCount)
60 && (mPortIde0Master == that.mPortIde0Master)
61 && (mPortIde0Slave == that.mPortIde0Slave)
62 && (mPortIde1Master == that.mPortIde1Master)
63 && (mPortIde1Slave == that.mPortIde1Slave));
64 }
65
66 /** Unique name of the storage controller. */
67 Utf8Str strName;
68 /** The connection type of thestorage controller. */
69 StorageBus_T mStorageBus;
70 /** Type of the Storage controller. */
71 StorageControllerType_T mStorageControllerType;
72 /** Instance number of the storage controller. */
73 ULONG mInstance;
74 /** Number of usable ports. */
75 ULONG mPortCount;
76
77 /** The following is only for the SATA controller atm. */
78 /** Port which acts as primary master for ide emulation. */
79 ULONG mPortIde0Master;
80 /** Port which acts as primary slave for ide emulation. */
81 ULONG mPortIde0Slave;
82 /** Port which acts as secondary master for ide emulation. */
83 ULONG mPortIde1Master;
84 /** Port which acts as secondary slave for ide emulation. */
85 ULONG mPortIde1Slave;
86};
87
88struct StorageController::Data
89{
[25199]90 Data()
91 { }
92
[25198]93 const ComObjPtr<Machine, ComWeakRef> pParent;
94 const ComObjPtr<StorageController> pPeer;
95
96 Backupable<BackupableStorageControllerData> bd;
97};
98
[17768]99// constructor / destructor
100/////////////////////////////////////////////////////////////////////////////
101
102HRESULT StorageController::FinalConstruct()
103{
104 return S_OK;
105}
106
107void StorageController::FinalRelease()
108{
109 uninit();
110}
111
112// public initializer/uninitializer for internal purposes only
113/////////////////////////////////////////////////////////////////////////////
114
115/**
116 * Initializes the storage controller object.
117 *
118 * @returns COM result indicator.
119 * @param aParent Pointer to our parent object.
120 * @param aName Name of the storage controller.
[24250]121 * @param aInstance Instance number of the storage controller.
[17768]122 */
[22173]123HRESULT StorageController::init(Machine *aParent,
124 const Utf8Str &aName,
[24250]125 StorageBus_T aStorageBus,
126 ULONG aInstance)
[17768]127{
[24250]128 LogFlowThisFunc(("aParent=%p aName=\"%s\" aInstance=%u\n",
129 aParent, aName.raw(), aInstance));
[17768]130
[22173]131 ComAssertRet(aParent && !aName.isEmpty(), E_INVALIDARG);
[17768]132 if ( (aStorageBus <= StorageBus_Null)
[23223]133 || (aStorageBus > StorageBus_Floppy))
[17768]134 return setError (E_INVALIDARG,
135 tr ("Invalid storage connection type"));
136
137 /* Enclose the state transition NotReady->InInit->Ready */
[21878]138 AutoInitSpan autoInitSpan(this);
139 AssertReturn(autoInitSpan.isOk(), E_FAIL);
[17768]140
[25198]141 m = new Data();
[17768]142
[25198]143 unconst(m->pParent) = aParent;
144 /* m->pPeer is left null */
145
[17768]146 /* register with parent early, since uninit() will unconditionally
147 * unregister on failure */
[25198]148 m->pParent->addDependentChild (this);
[17768]149
[25198]150 m->bd.allocate();
[17768]151
[25198]152 m->bd->strName = aName;
153 m->bd->mInstance = aInstance;
154 m->bd->mStorageBus = aStorageBus;
[17768]155
156 switch (aStorageBus)
157 {
158 case StorageBus_IDE:
[25198]159 m->bd->mPortCount = 2;
160 m->bd->mStorageControllerType = StorageControllerType_PIIX4;
[17768]161 break;
162 case StorageBus_SATA:
[25198]163 m->bd->mPortCount = 30;
164 m->bd->mStorageControllerType = StorageControllerType_IntelAhci;
[17768]165 break;
166 case StorageBus_SCSI:
[25198]167 m->bd->mPortCount = 16;
168 m->bd->mStorageControllerType = StorageControllerType_LsiLogic;
[17768]169 break;
[23223]170 case StorageBus_Floppy:
171 /** @todo allow 2 floppies later */
[25198]172 m->bd->mPortCount = 1;
173 m->bd->mStorageControllerType = StorageControllerType_I82078;
[23223]174 break;
[17768]175 }
176
177 /* Confirm a successful initialization */
178 autoInitSpan.setSucceeded();
179
180 return S_OK;
181}
182
183/**
184 * Initializes the object given another object
185 * (a kind of copy constructor). This object shares data with
186 * the object passed as an argument.
187 *
188 * @param aReshare
189 * When false, the original object will remain a data owner.
190 * Otherwise, data ownership will be transferred from the original
191 * object to this one.
192 *
193 * @note This object must be destroyed before the original object
194 * it shares data with is destroyed.
195 *
196 * @note Locks @a aThat object for writing if @a aReshare is @c true, or for
197 * reading if @a aReshare is false.
198 */
[25198]199HRESULT StorageController::init(Machine *aParent,
200 StorageController *aThat,
201 bool aReshare /* = false */)
[17768]202{
[21878]203 LogFlowThisFunc(("aParent=%p, aThat=%p, aReshare=%RTbool\n",
[17768]204 aParent, aThat, aReshare));
205
206 ComAssertRet (aParent && aThat, E_INVALIDARG);
207
208 /* Enclose the state transition NotReady->InInit->Ready */
[21878]209 AutoInitSpan autoInitSpan(this);
210 AssertReturn(autoInitSpan.isOk(), E_FAIL);
[17768]211
[25198]212 m = new Data();
[17768]213
[25198]214 unconst(m->pParent) = aParent;
215
[17768]216 /* register with parent early, since uninit() will unconditionally
217 * unregister on failure */
[25198]218 m->pParent->addDependentChild (this);
[17768]219
220 /* sanity */
221 AutoCaller thatCaller (aThat);
[21878]222 AssertComRCReturnRC(thatCaller.rc());
[17768]223
224 if (aReshare)
225 {
[25310]226 AutoWriteLock thatLock(aThat COMMA_LOCKVAL_SRC_POS);
[17768]227
[25198]228 unconst(aThat->m->pPeer) = this;
229 m->bd.attach (aThat->m->bd);
[17768]230 }
231 else
232 {
[25198]233 unconst(m->pPeer) = aThat;
[17768]234
[25310]235 AutoReadLock thatLock(aThat COMMA_LOCKVAL_SRC_POS);
[25198]236 m->bd.share (aThat->m->bd);
[17768]237 }
238
239 /* Confirm successful initialization */
240 autoInitSpan.setSucceeded();
241
242 return S_OK;
243}
244
245/**
246 * Initializes the storage controller object given another guest object
247 * (a kind of copy constructor). This object makes a private copy of data
248 * of the original object passed as an argument.
249 */
[25198]250HRESULT StorageController::initCopy(Machine *aParent, StorageController *aThat)
[17768]251{
[21878]252 LogFlowThisFunc(("aParent=%p, aThat=%p\n", aParent, aThat));
[17768]253
254 ComAssertRet (aParent && aThat, E_INVALIDARG);
255
256 /* Enclose the state transition NotReady->InInit->Ready */
[21878]257 AutoInitSpan autoInitSpan(this);
258 AssertReturn(autoInitSpan.isOk(), E_FAIL);
[17768]259
[25198]260 m = new Data();
[17768]261
[25198]262 unconst(m->pParent) = aParent;
263 /* m->pPeer is left null */
[17768]264
[25198]265 m->pParent->addDependentChild (this);
266
[17768]267 AutoCaller thatCaller (aThat);
[21878]268 AssertComRCReturnRC(thatCaller.rc());
[17768]269
[25310]270 AutoReadLock thatlock(aThat COMMA_LOCKVAL_SRC_POS);
[25198]271 m->bd.attachCopy (aThat->m->bd);
[17768]272
273 /* Confirm a successful initialization */
274 autoInitSpan.setSucceeded();
275
276 return S_OK;
277}
278
279
280/**
281 * Uninitializes the instance and sets the ready flag to FALSE.
282 * Called either from FinalRelease() or by the parent when it gets destroyed.
283 */
284void StorageController::uninit()
285{
[21878]286 LogFlowThisFunc(("\n"));
[17768]287
288 /* Enclose the state transition Ready->InUninit->NotReady */
[21878]289 AutoUninitSpan autoUninitSpan(this);
[17768]290 if (autoUninitSpan.uninitDone())
291 return;
292
[25198]293 m->bd.free();
[17768]294
[25198]295 m->pParent->removeDependentChild (this);
[17768]296
[25198]297 unconst(m->pPeer).setNull();
298 unconst(m->pParent).setNull();
299
300 delete m;
301 m = NULL;
[17768]302}
303
304
305// IStorageController properties
306/////////////////////////////////////////////////////////////////////////////
307STDMETHODIMP StorageController::COMGETTER(Name) (BSTR *aName)
308{
309 CheckComArgOutPointerValid(aName);
310
[21878]311 AutoCaller autoCaller(this);
[25149]312 if (FAILED(autoCaller.rc())) return autoCaller.rc();
[17768]313
314 /* mName is constant during life time, no need to lock */
[25198]315 m->bd.data()->strName.cloneTo(aName);
[17768]316
317 return S_OK;
318}
319
320STDMETHODIMP StorageController::COMGETTER(Bus) (StorageBus_T *aBus)
321{
322 CheckComArgOutPointerValid(aBus);
323
[21878]324 AutoCaller autoCaller(this);
[25149]325 if (FAILED(autoCaller.rc())) return autoCaller.rc();
[17768]326
[25310]327 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
[17768]328
[25198]329 *aBus = m->bd->mStorageBus;
[17768]330
331 return S_OK;
332}
333
334STDMETHODIMP StorageController::COMGETTER(ControllerType) (StorageControllerType_T *aControllerType)
335{
336 CheckComArgOutPointerValid(aControllerType);
337
[21878]338 AutoCaller autoCaller(this);
[25149]339 if (FAILED(autoCaller.rc())) return autoCaller.rc();
[17768]340
[25310]341 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
[17768]342
[25198]343 *aControllerType = m->bd->mStorageControllerType;
[17768]344
345 return S_OK;
346}
347
348STDMETHODIMP StorageController::COMSETTER(ControllerType) (StorageControllerType_T aControllerType)
349{
[21878]350 AutoCaller autoCaller(this);
[25149]351 if (FAILED(autoCaller.rc())) return autoCaller.rc();
[17768]352
[25310]353 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
[17768]354
355 HRESULT rc = S_OK;
356
[25198]357 switch (m->bd->mStorageBus)
[17768]358 {
359 case StorageBus_IDE:
360 {
361 if ( (aControllerType != StorageControllerType_PIIX3)
362 && (aControllerType != StorageControllerType_PIIX4)
363 && (aControllerType != StorageControllerType_ICH6))
364 rc = E_INVALIDARG;
365 break;
366 }
367 case StorageBus_SATA:
368 {
369 if (aControllerType != StorageControllerType_IntelAhci)
370 rc = E_INVALIDARG;
371 break;
372 }
373 case StorageBus_SCSI:
374 {
375 if ( (aControllerType != StorageControllerType_LsiLogic)
376 && (aControllerType != StorageControllerType_BusLogic))
377 rc = E_INVALIDARG;
378 break;
379 }
[23223]380 case StorageBus_Floppy:
381 {
382 if (aControllerType != StorageControllerType_I82078)
383 rc = E_INVALIDARG;
384 break;
385 }
[17768]386 default:
[25198]387 AssertMsgFailed(("Invalid controller type %d\n", m->bd->mStorageBus));
[17768]388 }
389
[21878]390 if (!SUCCEEDED(rc))
[17768]391 return setError(rc,
392 tr ("Invalid controller type %d"),
393 aControllerType);
394
[25198]395 m->bd->mStorageControllerType = aControllerType;
[17768]396
397 return S_OK;
398}
399
400STDMETHODIMP StorageController::COMGETTER(MaxDevicesPerPortCount) (ULONG *aMaxDevices)
401{
402 CheckComArgOutPointerValid(aMaxDevices);
403
[21878]404 AutoCaller autoCaller(this);
[25149]405 if (FAILED(autoCaller.rc())) return autoCaller.rc();
[17768]406
[25310]407 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
[17768]408
[23223]409 ComPtr<IVirtualBox> VBox;
[25198]410 HRESULT rc = m->pParent->COMGETTER(Parent)(VBox.asOutParam());
[23223]411 if (FAILED(rc))
412 return rc;
[17768]413
[23223]414 ComPtr<ISystemProperties> sysProps;
415 rc = VBox->COMGETTER(SystemProperties)(sysProps.asOutParam());
416 if (FAILED(rc))
417 return rc;
418
[25198]419 rc = sysProps->GetMaxDevicesPerPortForStorageBus(m->bd->mStorageBus, aMaxDevices);
[23223]420 return rc;
[17768]421}
422
423STDMETHODIMP StorageController::COMGETTER(MinPortCount) (ULONG *aMinPortCount)
424{
425 CheckComArgOutPointerValid(aMinPortCount);
426
[21878]427 AutoCaller autoCaller(this);
[25149]428 if (FAILED(autoCaller.rc())) return autoCaller.rc();
[17768]429
[25310]430 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
[17768]431
[23223]432 ComPtr<IVirtualBox> VBox;
[25198]433 HRESULT rc = m->pParent->COMGETTER(Parent)(VBox.asOutParam());
[23223]434 if (FAILED(rc))
435 return rc;
[17768]436
[23223]437 ComPtr<ISystemProperties> sysProps;
438 rc = VBox->COMGETTER(SystemProperties)(sysProps.asOutParam());
439 if (FAILED(rc))
440 return rc;
441
[25198]442 rc = sysProps->GetMinPortCountForStorageBus(m->bd->mStorageBus, aMinPortCount);
[23223]443 return rc;
[17768]444}
445
446STDMETHODIMP StorageController::COMGETTER(MaxPortCount) (ULONG *aMaxPortCount)
447{
448 CheckComArgOutPointerValid(aMaxPortCount);
449
[21878]450 AutoCaller autoCaller(this);
[25149]451 if (FAILED(autoCaller.rc())) return autoCaller.rc();
[17768]452
[25310]453 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
[17768]454
[23223]455 ComPtr<IVirtualBox> VBox;
[25198]456 HRESULT rc = m->pParent->COMGETTER(Parent)(VBox.asOutParam());
[23223]457 if (FAILED(rc))
458 return rc;
[17768]459
[23223]460 ComPtr<ISystemProperties> sysProps;
461 rc = VBox->COMGETTER(SystemProperties)(sysProps.asOutParam());
462 if (FAILED(rc))
463 return rc;
464
[25198]465 rc = sysProps->GetMaxPortCountForStorageBus(m->bd->mStorageBus, aMaxPortCount);
[23223]466 return rc;
[17768]467}
468
469
470STDMETHODIMP StorageController::COMGETTER(PortCount) (ULONG *aPortCount)
471{
472 CheckComArgOutPointerValid(aPortCount);
473
[21878]474 AutoCaller autoCaller(this);
[25149]475 if (FAILED(autoCaller.rc())) return autoCaller.rc();
[17768]476
[25310]477 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
[17768]478
[25198]479 *aPortCount = m->bd->mPortCount;
[17768]480
481 return S_OK;
482}
483
484
485STDMETHODIMP StorageController::COMSETTER(PortCount) (ULONG aPortCount)
486{
[21878]487 LogFlowThisFunc(("aPortCount=%u\n", aPortCount));
[17768]488
[25198]489 switch (m->bd->mStorageBus)
[17768]490 {
491 case StorageBus_SATA:
492 {
493 /* AHCI SATA supports a maximum of 30 ports. */
494 if ((aPortCount < 1) || (aPortCount > 30))
495 return setError (E_INVALIDARG,
496 tr ("Invalid port count: %lu (must be in range [%lu, %lu])"),
497 aPortCount, 1, 30);
498 break;
499 }
500 case StorageBus_SCSI:
501 {
502 /*
503 * SCSI does not support setting different ports.
504 * (doesn't make sense here either).
505 * The maximum and minimum is 16 and unless the callee
506 * tries to set a different value we return an error.
507 */
508 if (aPortCount != 16)
509 return setError (E_INVALIDARG,
510 tr ("Invalid port count: %lu (must be in range [%lu, %lu])"),
511 aPortCount, 16, 16);
512 break;
513 }
514 case StorageBus_IDE:
515 {
516 /*
[22173]517 * The port count is fixed to 2.
[17768]518 */
519 if (aPortCount != 2)
520 return setError (E_INVALIDARG,
521 tr ("Invalid port count: %lu (must be in range [%lu, %lu])"),
522 aPortCount, 2, 2);
523 break;
524 }
[23223]525 case StorageBus_Floppy:
526 {
527 /** @todo allow 2 floppies later */
528 /*
529 * The port count is fixed to 1.
530 */
531 if (aPortCount != 1)
532 return setError (E_INVALIDARG,
533 tr ("Invalid port count: %lu (must be in range [%lu, %lu])"),
534 aPortCount, 1, 1);
535 break;
536 }
[17768]537 default:
[25198]538 AssertMsgFailed(("Invalid controller type %d\n", m->bd->mStorageBus));
[17768]539 }
540
[21878]541 AutoCaller autoCaller(this);
[25149]542 if (FAILED(autoCaller.rc())) return autoCaller.rc();
[17768]543
544 /* the machine needs to be mutable */
[25198]545 Machine::AutoMutableStateDependency adep(m->pParent);
[25149]546 if (FAILED(adep.rc())) return adep.rc();
[17768]547
[25310]548 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
[17768]549
[25198]550 if (m->bd->mPortCount != aPortCount)
[17768]551 {
[25198]552 m->bd.backup();
553 m->bd->mPortCount = aPortCount;
[17768]554
555 /* leave the lock for safety */
556 alock.leave();
557
[25198]558 m->pParent->onStorageControllerChange ();
[17768]559 }
560
561 return S_OK;
562}
563
564STDMETHODIMP StorageController::COMGETTER(Instance) (ULONG *aInstance)
565{
[21878]566 AutoCaller autoCaller(this);
[25149]567 if (FAILED(autoCaller.rc())) return autoCaller.rc();
[17768]568
569 /* The machine doesn't need to be mutable. */
570
[25310]571 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
[17768]572
[25198]573 *aInstance = m->bd->mInstance;
[17768]574
575 return S_OK;
576}
577
578STDMETHODIMP StorageController::COMSETTER(Instance) (ULONG aInstance)
579{
[21878]580 AutoCaller autoCaller(this);
[25149]581 if (FAILED(autoCaller.rc())) return autoCaller.rc();
[17768]582
583 /* The machine doesn't need to be mutable. */
584
[25310]585 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
[17768]586
[25198]587 m->bd->mInstance = aInstance;
[17768]588
589 return S_OK;
590}
591
592// IStorageController methods
593/////////////////////////////////////////////////////////////////////////////
594
595STDMETHODIMP StorageController::GetIDEEmulationPort(LONG DevicePosition, LONG *aPortNumber)
596{
597 CheckComArgOutPointerValid(aPortNumber);
598
[21878]599 AutoCaller autoCaller(this);
[25149]600 if (FAILED(autoCaller.rc())) return autoCaller.rc();
[17768]601
[25310]602 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
[17768]603
[25198]604 if (m->bd->mStorageControllerType != StorageControllerType_IntelAhci)
[17768]605 return setError (E_NOTIMPL,
606 tr ("Invalid controller type"));
607
608 switch (DevicePosition)
609 {
610 case 0:
[25198]611 *aPortNumber = m->bd->mPortIde0Master;
[17768]612 break;
613 case 1:
[25198]614 *aPortNumber = m->bd->mPortIde0Slave;
[17768]615 break;
616 case 2:
[25198]617 *aPortNumber = m->bd->mPortIde1Master;
[17768]618 break;
619 case 3:
[25198]620 *aPortNumber = m->bd->mPortIde1Slave;
[17768]621 break;
622 default:
623 return E_INVALIDARG;
624 }
625
626 return S_OK;
627}
628
629STDMETHODIMP StorageController::SetIDEEmulationPort(LONG DevicePosition, LONG aPortNumber)
630{
[21878]631 AutoCaller autoCaller(this);
[25149]632 if (FAILED(autoCaller.rc())) return autoCaller.rc();
[17768]633
634 /* the machine needs to be mutable */
[25198]635 Machine::AutoMutableStateDependency adep(m->pParent);
[25149]636 if (FAILED(adep.rc())) return adep.rc();
[25310]637 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
[17768]638
[25198]639 if (m->bd->mStorageControllerType != StorageControllerType_IntelAhci)
[17768]640 return setError (E_NOTIMPL,
641 tr ("Invalid controller type"));
642
643 if ((aPortNumber < 0) || (aPortNumber >= 30))
644 return setError (E_INVALIDARG,
645 tr ("Invalid port number: %l (must be in range [%lu, %lu])"),
646 aPortNumber, 0, 29);
647
648 switch (DevicePosition)
649 {
650 case 0:
[25198]651 m->bd->mPortIde0Master = aPortNumber;
[17768]652 break;
653 case 1:
[25198]654 m->bd->mPortIde0Slave = aPortNumber;
[17768]655 break;
656 case 2:
[25198]657 m->bd->mPortIde1Master = aPortNumber;
[17768]658 break;
659 case 3:
[25198]660 m->bd->mPortIde1Slave = aPortNumber;
[17768]661 break;
662 default:
663 return E_INVALIDARG;
664 }
665
666 return S_OK;
667}
668
669// public methods only for internal purposes
670/////////////////////////////////////////////////////////////////////////////
671
[25198]672
673const Utf8Str& StorageController::getName() const
674{
675 return m->bd->strName;
676}
677
678StorageControllerType_T StorageController::getControllerType() const
679{
680 return m->bd->mStorageControllerType;
681}
682
683StorageBus_T StorageController::getStorageBus() const
684{
685 return m->bd->mStorageBus;
686}
687
688ULONG StorageController::getInstance() const
689{
690 return m->bd->mInstance;
691}
692
693bool StorageController::isModified()
694{
[25310]695 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
[25198]696 return m->bd.isBackedUp();
697}
698
699bool StorageController::isReallyModified()
700{
[25310]701 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
[25198]702 return m->bd.hasActualChanges();
703}
704
[17768]705/** @note Locks objects for writing! */
706bool StorageController::rollback()
707{
[21878]708 AutoCaller autoCaller(this);
[17768]709 AssertComRCReturn (autoCaller.rc(), false);
710
[25310]711 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
[17768]712
713 bool dataChanged = false;
714
[25198]715 if (m->bd.isBackedUp())
[17768]716 {
717 /* we need to check all data to see whether anything will be changed
718 * after rollback */
[25198]719 dataChanged = m->bd.hasActualChanges();
720 m->bd.rollback();
[17768]721 }
722
723 return dataChanged;
724}
725
726/**
727 * @note Locks this object for writing, together with the peer object (also
728 * for writing) if there is one.
729 */
730void StorageController::commit()
731{
732 /* sanity */
[21878]733 AutoCaller autoCaller(this);
[17768]734 AssertComRCReturnVoid (autoCaller.rc());
735
736 /* sanity too */
[25198]737 AutoCaller peerCaller (m->pPeer);
[17768]738 AssertComRCReturnVoid (peerCaller.rc());
739
[25198]740 /* lock both for writing since we modify both (m->pPeer is "master" so locked
[17768]741 * first) */
[25310]742 AutoMultiWriteLock2 alock(m->pPeer, this COMMA_LOCKVAL_SRC_POS);
[17768]743
[25198]744 if (m->bd.isBackedUp())
[17768]745 {
[25198]746 m->bd.commit();
747 if (m->pPeer)
[17768]748 {
749 // attach new data to the peer and reshare it
[25198]750 m->pPeer->m->bd.attach (m->bd);
[17768]751 }
752 }
753}
754
755/**
756 * Cancels sharing (if any) by making an independent copy of data.
757 * This operation also resets this object's peer to NULL.
758 *
759 * @note Locks this object for writing, together with the peer object
760 * represented by @a aThat (locked for reading).
761 */
762void StorageController::unshare()
763{
764 /* sanity */
[21878]765 AutoCaller autoCaller(this);
[17768]766 AssertComRCReturnVoid (autoCaller.rc());
767
768 /* sanity too */
[25198]769 AutoCaller peerCaller (m->pPeer);
[17768]770 AssertComRCReturnVoid (peerCaller.rc());
771
[25198]772 /* peer is not modified, lock it for reading (m->pPeer is "master" so locked
[17768]773 * first) */
[25310]774 AutoReadLock rl(m->pPeer COMMA_LOCKVAL_SRC_POS);
775 AutoWriteLock wl(this COMMA_LOCKVAL_SRC_POS);
[17768]776
[25198]777 if (m->bd.isShared())
[17768]778 {
[25198]779 if (!m->bd.isBackedUp())
780 m->bd.backup();
[17768]781
[25198]782 m->bd.commit();
[17768]783 }
784
[25198]785 unconst(m->pPeer).setNull();
[17768]786}
787
[25198]788const ComObjPtr<Machine, ComWeakRef>& StorageController::getMachine()
789{
790 return m->pParent;
791}
792
793ComObjPtr<StorageController> StorageController::getPeer()
794{
795 return m->pPeer;
796}
797
[17768]798// private methods
799/////////////////////////////////////////////////////////////////////////////
[25198]800
801
[17768]802/* vi: set tabstop=4 shiftwidth=4 expandtab: */
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use