VirtualBox

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

Last change on this file since 25877 was 25860, checked in by vboxsync, 15 years ago

Main: cleanup: get rid of VirtualBoxBaseProto, move AutoCaller*/*Span* classes out of VirtualBoxBaseProto class scope and into separate header; move CombinedProgress into separate header (it's only used by Console any more)

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