VirtualBox

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

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

Main: Remove IoBackendType in StorageController and have a boolean setting fUseAsyncHostIOMgr instead; change XML settings and frontends accordingly; change VBoxManage storagectl syntax to --hostiocache on|off as well

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