VirtualBox

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

Last change on this file since 28851 was 28800, checked in by vboxsync, 15 years ago

Automated rebranding to Oracle copyright/license strings via filemuncher

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