MediumImpl.cpp revision 8dbf70ba2345e69b0b6d45c38cf1add0ef10591c
77b1a2d8b5dbe2c0b5200794914239fee3c8ee5dvboxsync/* $Id$ */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/** @file
77b1a2d8b5dbe2c0b5200794914239fee3c8ee5dvboxsync * VirtualBox COM class implementation
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/*
d1aab951b0bd1de1a8a51daca46fce06daaed8d7vboxsync * Copyright (C) 2008-2010 Oracle Corporation
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync *
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * available from http://www.virtualbox.org. This file is free software;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * you can redistribute it and/or modify it under the terms of the GNU
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * General Public License (GPL) as published by the Free Software
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync#include "MediumImpl.h"
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync#include "ProgressImpl.h"
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync#include "SystemPropertiesImpl.h"
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync#include "VirtualBoxImpl.h"
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
cd6f71bc352f550074f1ba2c830a2cf2f0b3dd46vboxsync#include "AutoCaller.h"
43747b1f0bc8302a238fb35e55857a5e9aa1933dvboxsync#include "Logging.h"
43747b1f0bc8302a238fb35e55857a5e9aa1933dvboxsync
43747b1f0bc8302a238fb35e55857a5e9aa1933dvboxsync#include <VBox/com/array.h>
16a9adc14900ca18e6909679a579f6833425e030vboxsync#include <VBox/com/SupportErrorInfo.h>
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync#include <VBox/err.h>
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync#include <VBox/settings.h>
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync#include <iprt/param.h>
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync#include <iprt/path.h>
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync#include <iprt/file.h>
a9f41cb889f53e8407561a6155052c441eb0fc5fvboxsync#include <iprt/tcp.h>
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync#include <VBox/VBoxHDD.h>
b0b15690f00527424b2d5fb88456d747252322f7vboxsync
47579c4cc64e7dff9b4de48841a2c4df3b96ab38vboxsync#include <algorithm>
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
efff36b306e370346025647a158689021df2e1d1vboxsync////////////////////////////////////////////////////////////////////////////////
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync//
590bfe12ce22cd3716448fbb9f4dc51664bfe5e2vboxsync// Medium data definition
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync//
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync////////////////////////////////////////////////////////////////////////////////
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync/** Describes how a machine refers to this image. */
30c39307775310ba50de9d9b74f1ea9e12524102vboxsyncstruct BackRef
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync{
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync /** Equality predicate for stdc++. */
590bfe12ce22cd3716448fbb9f4dc51664bfe5e2vboxsync struct EqualsTo : public std::unary_function <BackRef, bool>
efff36b306e370346025647a158689021df2e1d1vboxsync {
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync explicit EqualsTo(const Guid &aMachineId) : machineId(aMachineId) {}
f5e53763b0a581b0299e98028c6c52192eb06785vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync bool operator()(const argument_type &aThat) const
efff36b306e370346025647a158689021df2e1d1vboxsync {
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync return aThat.machineId == machineId;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync }
efff36b306e370346025647a158689021df2e1d1vboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync const Guid machineId;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync };
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync typedef std::list<Guid> GuidList;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync BackRef(const Guid &aMachineId,
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync const Guid &aSnapshotId = Guid::Empty)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync : machineId(aMachineId),
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync fInCurState(aSnapshotId.isEmpty())
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync {
9496f2d398b49813176939d7a339ae513d5175efvboxsync if (!aSnapshotId.isEmpty())
9496f2d398b49813176939d7a339ae513d5175efvboxsync llSnapshotIds.push_back(aSnapshotId);
9496f2d398b49813176939d7a339ae513d5175efvboxsync }
9496f2d398b49813176939d7a339ae513d5175efvboxsync
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync Guid machineId;
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync bool fInCurState : 1;
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync GuidList llSnapshotIds;
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync};
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsynctypedef std::list<BackRef> BackRefList;
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsyncstruct Medium::Data
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync{
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync Data()
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync : pVirtualBox(NULL),
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync state(MediumState_NotCreated),
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync size(0),
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync readers(0),
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync preLockState(MediumState_NotCreated),
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync queryInfoSem(NIL_RTSEMEVENTMULTI),
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync queryInfoRunning(false),
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync type(MediumType_Normal),
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync devType(DeviceType_HardDisk),
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync logicalSize(0),
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync hddOpenMode(OpenReadWrite),
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync autoReset(false),
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync setImageId(false),
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync setParentId(false),
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync hostDrive(false),
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync implicit(false),
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync numCreateDiffTasks(0),
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync vdDiskIfaces(NULL)
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync {}
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync /** weak VirtualBox parent */
7766bf675357fd940d8c49e69a5d72dc6eaa6be4vboxsync VirtualBox * const pVirtualBox;
7766bf675357fd940d8c49e69a5d72dc6eaa6be4vboxsync
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync const Guid id;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync Utf8Str strDescription;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync MediumState_T state;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync Utf8Str strLocation;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync Utf8Str strLocationFull;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync uint64_t size;
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync Utf8Str strLastAccessError;
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync // pParent and llChildren are protected by VirtualBox::getMediaTreeLockHandle()
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync ComObjPtr<Medium> pParent;
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync MediaList llChildren; // to add a child, just call push_back; to remove a child, call child->deparent() which does a lookup
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync BackRefList backRefs;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync size_t readers;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync MediumState_T preLockState;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync RTSEMEVENTMULTI queryInfoSem;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync bool queryInfoRunning : 1;
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync
cab115cfa31c584def7069312a1e23c3fc88533bvboxsync const Utf8Str strFormat;
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync ComObjPtr<MediumFormat> formatObj;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync MediumType_T type;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync DeviceType_T devType;
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync uint64_t logicalSize; /*< In MBytes. */
21029597fc4b76d0db0c9542daee201447281781vboxsync
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync HDDOpenMode hddOpenMode;
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync bool autoReset : 1;
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync /** the following members are invalid after changing UUID on open */
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync bool setImageId : 1;
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync bool setParentId : 1;
c0a370e600bb60153a269fb32b5f709347c35768vboxsync const Guid imageId;
ad27e1d5e48ca41245120c331cc88b50464813cevboxsync const Guid parentId;
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsync bool hostDrive : 1;
9496f2d398b49813176939d7a339ae513d5175efvboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsync typedef std::map <Bstr, Bstr> PropertyMap;
9496f2d398b49813176939d7a339ae513d5175efvboxsync PropertyMap properties;
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync bool implicit : 1;
61d064a54f03596920c3918f58ecc7764074a5d8vboxsync
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync uint32_t numCreateDiffTasks;
16a9adc14900ca18e6909679a579f6833425e030vboxsync
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync Utf8Str vdError; /*< Error remembered by the VD error callback. */
16a9adc14900ca18e6909679a579f6833425e030vboxsync
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync VDINTERFACE vdIfError;
16a9adc14900ca18e6909679a579f6833425e030vboxsync VDINTERFACEERROR vdIfCallsError;
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync VDINTERFACE vdIfConfig;
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync VDINTERFACECONFIG vdIfCallsConfig;
16a9adc14900ca18e6909679a579f6833425e030vboxsync
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync VDINTERFACE vdIfTcpNet;
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync VDINTERFACETCPNET vdIfCallsTcpNet;
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync PVDINTERFACE vdDiskIfaces;
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync};
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync////////////////////////////////////////////////////////////////////////////////
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync//
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync// Globals
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync//
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync////////////////////////////////////////////////////////////////////////////////
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync/**
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync * Medium::Task class for asynchronous operations.
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync *
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync * @note Instances of this class must be created using new() because the
b5ad839a3757b305d4e98d7264da2b53c9cd27f0vboxsync * task thread function will delete them when the task is complete.
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync *
61b5982fad4660d0fe3dd6ceba9eda85eb32f7e8vboxsync * @note The constructor of this class adds a caller on the managed Medium
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync * object which is automatically released upon destruction.
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync */
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsyncclass Medium::Task
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync{
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsyncpublic:
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync Task(Medium *aMedium, Progress *aProgress)
009d45aa55691312278d41edb20154dc208d9cd8vboxsync : mVDOperationIfaces(NULL),
009d45aa55691312278d41edb20154dc208d9cd8vboxsync m_pfNeedsSaveSettings(NULL),
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync mMedium(aMedium),
1741b757f7a570a7e6d48db46c3f4cd50f2ee296vboxsync mMediumCaller(aMedium),
1741b757f7a570a7e6d48db46c3f4cd50f2ee296vboxsync mThread(NIL_RTTHREAD),
1741b757f7a570a7e6d48db46c3f4cd50f2ee296vboxsync mProgress(aProgress)
203cad92999b4792bf61b4b65e1e2abfe08f5664vboxsync {
203cad92999b4792bf61b4b65e1e2abfe08f5664vboxsync AssertReturnVoidStmt(aMedium, mRC = E_FAIL);
203cad92999b4792bf61b4b65e1e2abfe08f5664vboxsync mRC = mMediumCaller.rc();
1741b757f7a570a7e6d48db46c3f4cd50f2ee296vboxsync if (FAILED(mRC))
1741b757f7a570a7e6d48db46c3f4cd50f2ee296vboxsync return;
c5abe3ea9c7ac6dec34f42af30612534bea951ffvboxsync
c5abe3ea9c7ac6dec34f42af30612534bea951ffvboxsync /* Set up a per-operation progress interface, can be used freely (for
c5abe3ea9c7ac6dec34f42af30612534bea951ffvboxsync * binary operations you can use it either on the source or target). */
c5abe3ea9c7ac6dec34f42af30612534bea951ffvboxsync mVDIfCallsProgress.cbSize = sizeof(VDINTERFACEPROGRESS);
eeebcc1f7aedfdbcaf7c4dae90ad932d5d9c03c8vboxsync mVDIfCallsProgress.enmInterface = VDINTERFACETYPE_PROGRESS;
eeebcc1f7aedfdbcaf7c4dae90ad932d5d9c03c8vboxsync mVDIfCallsProgress.pfnProgress = vdProgressCall;
1741b757f7a570a7e6d48db46c3f4cd50f2ee296vboxsync int vrc = VDInterfaceAdd(&mVDIfProgress,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync "Medium::Task::vdInterfaceProgress",
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync VDINTERFACETYPE_PROGRESS,
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync &mVDIfCallsProgress,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync mProgress,
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync &mVDOperationIfaces);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync AssertRC(vrc);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync if (RT_FAILURE(vrc))
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync mRC = E_FAIL;
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync }
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync // Make all destructors virtual. Just in case.
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync virtual ~Task()
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync {}
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync HRESULT rc() const { return mRC; }
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync bool isOk() const { return SUCCEEDED(rc()); }
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync static int fntMediumTask(RTTHREAD aThread, void *pvUser);
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync bool isAsync() { return mThread != NIL_RTTHREAD; }
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync PVDINTERFACE mVDOperationIfaces;
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync // Whether the caller needs to call VirtualBox::saveSettings() after
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync // the task function returns. Only used in synchronous (wait) mode;
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync // otherwise the task will save the settings itself.
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync bool *m_pfNeedsSaveSettings;
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync const ComObjPtr<Medium> mMedium;
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync AutoCaller mMediumCaller;
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync friend HRESULT Medium::runNow(Medium::Task*, bool*);
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsyncprotected:
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync HRESULT mRC;
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync RTTHREAD mThread;
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsyncprivate:
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync virtual HRESULT handler() = 0;
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync const ComObjPtr<Progress> mProgress;
16a9adc14900ca18e6909679a579f6833425e030vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync static DECLCALLBACK(int) vdProgressCall(void *pvUser, unsigned uPercent);
16a9adc14900ca18e6909679a579f6833425e030vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync VDINTERFACE mVDIfProgress;
16a9adc14900ca18e6909679a579f6833425e030vboxsync VDINTERFACEPROGRESS mVDIfCallsProgress;
16a9adc14900ca18e6909679a579f6833425e030vboxsync};
16a9adc14900ca18e6909679a579f6833425e030vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsyncclass Medium::CreateBaseTask : public Medium::Task
16a9adc14900ca18e6909679a579f6833425e030vboxsync{
16a9adc14900ca18e6909679a579f6833425e030vboxsyncpublic:
16a9adc14900ca18e6909679a579f6833425e030vboxsync CreateBaseTask(Medium *aMedium,
16a9adc14900ca18e6909679a579f6833425e030vboxsync Progress *aProgress,
16a9adc14900ca18e6909679a579f6833425e030vboxsync uint64_t aSize,
16a9adc14900ca18e6909679a579f6833425e030vboxsync MediumVariant_T aVariant)
16a9adc14900ca18e6909679a579f6833425e030vboxsync : Medium::Task(aMedium, aProgress),
16a9adc14900ca18e6909679a579f6833425e030vboxsync mSize(aSize),
16a9adc14900ca18e6909679a579f6833425e030vboxsync mVariant(aVariant)
16a9adc14900ca18e6909679a579f6833425e030vboxsync {}
16a9adc14900ca18e6909679a579f6833425e030vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync uint64_t mSize;
16a9adc14900ca18e6909679a579f6833425e030vboxsync MediumVariant_T mVariant;
16a9adc14900ca18e6909679a579f6833425e030vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsyncprivate:
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync virtual HRESULT handler();
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync};
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsyncclass Medium::CreateDiffTask : public Medium::Task
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync{
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsyncpublic:
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync CreateDiffTask(Medium *aMedium,
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync Progress *aProgress,
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync Medium *aTarget,
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync MediumVariant_T aVariant,
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync MediumLockList *aMediumLockList,
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync bool fKeepMediumLockList = false)
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync : Medium::Task(aMedium, aProgress),
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync mpMediumLockList(aMediumLockList),
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync mTarget(aTarget),
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync mVariant(aVariant),
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync mTargetCaller(aTarget),
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync mfKeepMediumLockList(fKeepMediumLockList)
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync {
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync AssertReturnVoidStmt(aTarget != NULL, mRC = E_FAIL);
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync mRC = mTargetCaller.rc();
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync if (FAILED(mRC))
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync return;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync }
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync ~CreateDiffTask()
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync {
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync if (!mfKeepMediumLockList && mpMediumLockList)
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync delete mpMediumLockList;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync }
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync MediumLockList *mpMediumLockList;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync const ComObjPtr<Medium> mTarget;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync MediumVariant_T mVariant;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsyncprivate:
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync virtual HRESULT handler();
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync
a9d49c8f2b28a72e6a4db86eee91e4569290157bvboxsync AutoCaller mTargetCaller;
a9d49c8f2b28a72e6a4db86eee91e4569290157bvboxsync bool mfKeepMediumLockList;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync};
a9d49c8f2b28a72e6a4db86eee91e4569290157bvboxsync
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsyncclass Medium::CloneTask : public Medium::Task
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync{
9496f2d398b49813176939d7a339ae513d5175efvboxsyncpublic:
9496f2d398b49813176939d7a339ae513d5175efvboxsync CloneTask(Medium *aMedium,
9496f2d398b49813176939d7a339ae513d5175efvboxsync Progress *aProgress,
9496f2d398b49813176939d7a339ae513d5175efvboxsync Medium *aTarget,
59d7f5939d42ad9d344fbad8401e00a900db92c5vboxsync MediumVariant_T aVariant,
59d7f5939d42ad9d344fbad8401e00a900db92c5vboxsync Medium *aParent,
22ec733a5e041fcdfe02fce2eafc9faf8b0077ddvboxsync MediumLockList *aSourceMediumLockList,
9496f2d398b49813176939d7a339ae513d5175efvboxsync MediumLockList *aTargetMediumLockList,
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync bool fKeepSourceMediumLockList = false,
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync bool fKeepTargetMediumLockList = false)
9496f2d398b49813176939d7a339ae513d5175efvboxsync : Medium::Task(aMedium, aProgress),
aa834e89e076db44fa8fe82d177748f0a45d14c2vboxsync mTarget(aTarget),
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync mParent(aParent),
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync mpSourceMediumLockList(aSourceMediumLockList),
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync mpTargetMediumLockList(aTargetMediumLockList),
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync mVariant(aVariant),
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync mTargetCaller(aTarget),
7766bf675357fd940d8c49e69a5d72dc6eaa6be4vboxsync mParentCaller(aParent),
a0a5ab4e085a7ee5b95bdfae04cec7de95792c3cvboxsync mfKeepSourceMediumLockList(fKeepSourceMediumLockList),
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync mfKeepTargetMediumLockList(fKeepTargetMediumLockList)
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync {
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync AssertReturnVoidStmt(aTarget != NULL, mRC = E_FAIL);
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync mRC = mTargetCaller.rc();
d5ea45cc92d7f1d3ade8189944531f665bfe8ed5vboxsync if (FAILED(mRC))
5d0d754550d06b7d59a935e59caaf814462d53ccvboxsync return;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /* aParent may be NULL */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync mRC = mParentCaller.rc();
d5ea45cc92d7f1d3ade8189944531f665bfe8ed5vboxsync if (FAILED(mRC))
f687f34bd232be13744edbc0cc5155fa5d4540edvboxsync return;
d5ea45cc92d7f1d3ade8189944531f665bfe8ed5vboxsync AssertReturnVoidStmt(aSourceMediumLockList != NULL, mRC = E_FAIL);
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync AssertReturnVoidStmt(aTargetMediumLockList != NULL, mRC = E_FAIL);
9496f2d398b49813176939d7a339ae513d5175efvboxsync }
9496f2d398b49813176939d7a339ae513d5175efvboxsync
bbede9c189def47a9880f0ffb03c0c230c774185vboxsync ~CloneTask()
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync {
468c2bcb36eb9a032f5dd0fcb34db10bd58e9996vboxsync if (!mfKeepSourceMediumLockList && mpSourceMediumLockList)
bbede9c189def47a9880f0ffb03c0c230c774185vboxsync delete mpSourceMediumLockList;
9496f2d398b49813176939d7a339ae513d5175efvboxsync if (!mfKeepTargetMediumLockList && mpTargetMediumLockList)
16a9adc14900ca18e6909679a579f6833425e030vboxsync delete mpTargetMediumLockList;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync }
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsync const ComObjPtr<Medium> mTarget;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync const ComObjPtr<Medium> mParent;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync MediumLockList *mpSourceMediumLockList;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync MediumLockList *mpTargetMediumLockList;
7766bf675357fd940d8c49e69a5d72dc6eaa6be4vboxsync MediumVariant_T mVariant;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsyncprivate:
ffbe6daf773e38167f3cabaf1f063d84ecd063e9vboxsync virtual HRESULT handler();
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync AutoCaller mTargetCaller;
fbf08fabb4c4b383d6aa2830c2bd5b943a26f10cvboxsync AutoCaller mParentCaller;
fbf08fabb4c4b383d6aa2830c2bd5b943a26f10cvboxsync bool mfKeepSourceMediumLockList;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync bool mfKeepTargetMediumLockList;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync};
a0a5ab4e085a7ee5b95bdfae04cec7de95792c3cvboxsync
a0a5ab4e085a7ee5b95bdfae04cec7de95792c3cvboxsyncclass Medium::CompactTask : public Medium::Task
a0a5ab4e085a7ee5b95bdfae04cec7de95792c3cvboxsync{
61d064a54f03596920c3918f58ecc7764074a5d8vboxsyncpublic:
ba74637cb4d2e749337d51ccbfb1038bdd3e2092vboxsync CompactTask(Medium *aMedium,
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync Progress *aProgress,
ba74637cb4d2e749337d51ccbfb1038bdd3e2092vboxsync MediumLockList *aMediumLockList,
61d064a54f03596920c3918f58ecc7764074a5d8vboxsync bool fKeepMediumLockList = false)
ba74637cb4d2e749337d51ccbfb1038bdd3e2092vboxsync : Medium::Task(aMedium, aProgress),
61b5982fad4660d0fe3dd6ceba9eda85eb32f7e8vboxsync mpMediumLockList(aMediumLockList),
61b5982fad4660d0fe3dd6ceba9eda85eb32f7e8vboxsync mfKeepMediumLockList(fKeepMediumLockList)
adefd5e9babba486cba0cfae52f5a0f6c8c4ef24vboxsync {
61d064a54f03596920c3918f58ecc7764074a5d8vboxsync AssertReturnVoidStmt(aMediumLockList != NULL, mRC = E_FAIL);
61d064a54f03596920c3918f58ecc7764074a5d8vboxsync }
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync
b5ad839a3757b305d4e98d7264da2b53c9cd27f0vboxsync ~CompactTask()
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync {
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync if (!mfKeepMediumLockList && mpMediumLockList)
b5ad839a3757b305d4e98d7264da2b53c9cd27f0vboxsync delete mpMediumLockList;
b5ad839a3757b305d4e98d7264da2b53c9cd27f0vboxsync }
b5ad839a3757b305d4e98d7264da2b53c9cd27f0vboxsync
b5ad839a3757b305d4e98d7264da2b53c9cd27f0vboxsync MediumLockList *mpMediumLockList;
b5ad839a3757b305d4e98d7264da2b53c9cd27f0vboxsync
a0a5ab4e085a7ee5b95bdfae04cec7de95792c3cvboxsyncprivate:
a0a5ab4e085a7ee5b95bdfae04cec7de95792c3cvboxsync virtual HRESULT handler();
b5ad839a3757b305d4e98d7264da2b53c9cd27f0vboxsync
b5ad839a3757b305d4e98d7264da2b53c9cd27f0vboxsync bool mfKeepMediumLockList;
b5ad839a3757b305d4e98d7264da2b53c9cd27f0vboxsync};
b5ad839a3757b305d4e98d7264da2b53c9cd27f0vboxsync
b5ad839a3757b305d4e98d7264da2b53c9cd27f0vboxsyncclass Medium::ResetTask : public Medium::Task
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync{
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsyncpublic:
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync ResetTask(Medium *aMedium,
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync Progress *aProgress,
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync MediumLockList *aMediumLockList,
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync bool fKeepMediumLockList = false)
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync : Medium::Task(aMedium, aProgress),
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync mpMediumLockList(aMediumLockList),
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync mfKeepMediumLockList(fKeepMediumLockList)
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync {}
9496f2d398b49813176939d7a339ae513d5175efvboxsync
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync ~ResetTask()
9496f2d398b49813176939d7a339ae513d5175efvboxsync {
9496f2d398b49813176939d7a339ae513d5175efvboxsync if (!mfKeepMediumLockList && mpMediumLockList)
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync delete mpMediumLockList;
9496f2d398b49813176939d7a339ae513d5175efvboxsync }
16a9adc14900ca18e6909679a579f6833425e030vboxsync
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync MediumLockList *mpMediumLockList;
9496f2d398b49813176939d7a339ae513d5175efvboxsync
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsyncprivate:
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync virtual HRESULT handler();
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync bool mfKeepMediumLockList;
9496f2d398b49813176939d7a339ae513d5175efvboxsync};
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsyncclass Medium::DeleteTask : public Medium::Task
9496f2d398b49813176939d7a339ae513d5175efvboxsync{
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsyncpublic:
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync DeleteTask(Medium *aMedium,
9496f2d398b49813176939d7a339ae513d5175efvboxsync Progress *aProgress,
16a9adc14900ca18e6909679a579f6833425e030vboxsync MediumLockList *aMediumLockList,
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync bool fKeepMediumLockList = false)
a9f41cb889f53e8407561a6155052c441eb0fc5fvboxsync : Medium::Task(aMedium, aProgress),
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync mpMediumLockList(aMediumLockList),
9496f2d398b49813176939d7a339ae513d5175efvboxsync mfKeepMediumLockList(fKeepMediumLockList)
a0a5ab4e085a7ee5b95bdfae04cec7de95792c3cvboxsync {}
a0a5ab4e085a7ee5b95bdfae04cec7de95792c3cvboxsync
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync ~DeleteTask()
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync {
9496f2d398b49813176939d7a339ae513d5175efvboxsync if (!mfKeepMediumLockList && mpMediumLockList)
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync delete mpMediumLockList;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync }
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync MediumLockList *mpMediumLockList;
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsyncprivate:
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync virtual HRESULT handler();
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync bool mfKeepMediumLockList;
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync};
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsyncclass Medium::MergeTask : public Medium::Task
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync{
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsyncpublic:
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync MergeTask(Medium *aMedium,
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync Medium *aTarget,
7766bf675357fd940d8c49e69a5d72dc6eaa6be4vboxsync bool fMergeForward,
9496f2d398b49813176939d7a339ae513d5175efvboxsync Medium *aParentForTarget,
9496f2d398b49813176939d7a339ae513d5175efvboxsync const MediaList &aChildrenToReparent,
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync Progress *aProgress,
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync MediumLockList *aMediumLockList,
9496f2d398b49813176939d7a339ae513d5175efvboxsync bool fKeepMediumLockList = false)
16a9adc14900ca18e6909679a579f6833425e030vboxsync : Medium::Task(aMedium, aProgress),
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync mTarget(aTarget),
a9f41cb889f53e8407561a6155052c441eb0fc5fvboxsync mfMergeForward(fMergeForward),
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync mParentForTarget(aParentForTarget),
9496f2d398b49813176939d7a339ae513d5175efvboxsync mChildrenToReparent(aChildrenToReparent),
a0a5ab4e085a7ee5b95bdfae04cec7de95792c3cvboxsync mpMediumLockList(aMediumLockList),
a0a5ab4e085a7ee5b95bdfae04cec7de95792c3cvboxsync mTargetCaller(aTarget),
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync mParentForTargetCaller(aParentForTarget),
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync mfChildrenCaller(false),
9496f2d398b49813176939d7a339ae513d5175efvboxsync mfKeepMediumLockList(fKeepMediumLockList)
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync {
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync AssertReturnVoidStmt(aMediumLockList != NULL, mRC = E_FAIL);
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync for (MediaList::const_iterator it = mChildrenToReparent.begin();
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync it != mChildrenToReparent.end();
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync ++it)
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync {
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync HRESULT rc2 = (*it)->addCaller();
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync if (FAILED(rc2))
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync {
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync mRC = E_FAIL;
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync for (MediaList::const_iterator it2 = mChildrenToReparent.begin();
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync it2 != it;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync --it2)
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync {
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync (*it2)->releaseCaller();
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync }
7766bf675357fd940d8c49e69a5d72dc6eaa6be4vboxsync return;
9496f2d398b49813176939d7a339ae513d5175efvboxsync }
9496f2d398b49813176939d7a339ae513d5175efvboxsync }
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync mfChildrenCaller = true;
9496f2d398b49813176939d7a339ae513d5175efvboxsync }
16a9adc14900ca18e6909679a579f6833425e030vboxsync
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync ~MergeTask()
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync {
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync if (!mfKeepMediumLockList && mpMediumLockList)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync delete mpMediumLockList;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (mfChildrenCaller)
a0a5ab4e085a7ee5b95bdfae04cec7de95792c3cvboxsync {
a0a5ab4e085a7ee5b95bdfae04cec7de95792c3cvboxsync for (MediaList::const_iterator it = mChildrenToReparent.begin();
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync it != mChildrenToReparent.end();
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync ++it)
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync {
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync (*it)->releaseCaller();
9496f2d398b49813176939d7a339ae513d5175efvboxsync }
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync }
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync }
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync const ComObjPtr<Medium> mTarget;
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync bool mfMergeForward;
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync /* When mChildrenToReparent is empty then mParentForTarget is non-null.
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync * In other words: they are used in different cases. */
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync const ComObjPtr<Medium> mParentForTarget;
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync MediaList mChildrenToReparent;
9496f2d398b49813176939d7a339ae513d5175efvboxsync MediumLockList *mpMediumLockList;
7766bf675357fd940d8c49e69a5d72dc6eaa6be4vboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsyncprivate:
9496f2d398b49813176939d7a339ae513d5175efvboxsync virtual HRESULT handler();
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync
a9f41cb889f53e8407561a6155052c441eb0fc5fvboxsync AutoCaller mTargetCaller;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync AutoCaller mParentForTargetCaller;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync bool mfChildrenCaller;
9496f2d398b49813176939d7a339ae513d5175efvboxsync bool mfKeepMediumLockList;
16a9adc14900ca18e6909679a579f6833425e030vboxsync};
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsync/**
a0a5ab4e085a7ee5b95bdfae04cec7de95792c3cvboxsync * Thread function for time-consuming medium tasks.
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync *
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync * @param pvUser Pointer to the Medium::Task instance.
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync */
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync/* static */
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsyncDECLCALLBACK(int) Medium::Task::fntMediumTask(RTTHREAD aThread, void *pvUser)
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync{
9496f2d398b49813176939d7a339ae513d5175efvboxsync LogFlowFuncEnter();
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync AssertReturn(pvUser, (int)E_INVALIDARG);
a9f41cb889f53e8407561a6155052c441eb0fc5fvboxsync Medium::Task *pTask = static_cast<Medium::Task *>(pvUser);
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync pTask->mThread = aThread;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync HRESULT rc = pTask->handler();
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsync /* complete the progress if run asynchronously */
a0a5ab4e085a7ee5b95bdfae04cec7de95792c3cvboxsync if (pTask->isAsync())
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync {
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync if (!pTask->mProgress.isNull())
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync pTask->mProgress->notifyComplete(rc);
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync }
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync /* pTask is no longer needed, delete it. */
9496f2d398b49813176939d7a339ae513d5175efvboxsync delete pTask;
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync LogFlowFunc(("rc=%Rhrc\n", rc));
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync LogFlowFuncLeave();
16a9adc14900ca18e6909679a579f6833425e030vboxsync
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync return (int)rc;
9496f2d398b49813176939d7a339ae513d5175efvboxsync}
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync/**
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync * PFNVDPROGRESS callback handler for Task operations.
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync *
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync * @param pvUser Pointer to the Progress instance.
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync * @param uPercent Completetion precentage (0-100).
9496f2d398b49813176939d7a339ae513d5175efvboxsync */
9496f2d398b49813176939d7a339ae513d5175efvboxsync/*static*/
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsyncDECLCALLBACK(int) Medium::Task::vdProgressCall(void *pvUser, unsigned uPercent)
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsync{
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsync Progress *that = static_cast<Progress *>(pvUser);
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsync
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsync if (that != NULL)
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsync {
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsync /* update the progress object, capping it at 99% as the final percent
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsync * is used for additional operations like setting the UUIDs and similar. */
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsync HRESULT rc = that->SetCurrentOperationProgress(uPercent * 99 / 100);
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsync if (FAILED(rc))
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsync {
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsync if (rc == E_FAIL)
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsync return VERR_CANCELLED;
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync else
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsync return VERR_INVALID_STATE;
369a8817da53dbd5ea6ac360ca0376dba003cde4vboxsync }
59d7f5939d42ad9d344fbad8401e00a900db92c5vboxsync }
59d7f5939d42ad9d344fbad8401e00a900db92c5vboxsync
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync return VINF_SUCCESS;
16a9adc14900ca18e6909679a579f6833425e030vboxsync}
16a9adc14900ca18e6909679a579f6833425e030vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync/**
16a9adc14900ca18e6909679a579f6833425e030vboxsync * Implementation code for the "create base" task.
16a9adc14900ca18e6909679a579f6833425e030vboxsync */
16a9adc14900ca18e6909679a579f6833425e030vboxsyncHRESULT Medium::CreateBaseTask::handler()
16a9adc14900ca18e6909679a579f6833425e030vboxsync{
16a9adc14900ca18e6909679a579f6833425e030vboxsync return mMedium->taskCreateBaseHandler(*this);
16a9adc14900ca18e6909679a579f6833425e030vboxsync}
16a9adc14900ca18e6909679a579f6833425e030vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync/**
16a9adc14900ca18e6909679a579f6833425e030vboxsync * Implementation code for the "create diff" task.
16a9adc14900ca18e6909679a579f6833425e030vboxsync */
16a9adc14900ca18e6909679a579f6833425e030vboxsyncHRESULT Medium::CreateDiffTask::handler()
16a9adc14900ca18e6909679a579f6833425e030vboxsync{
16a9adc14900ca18e6909679a579f6833425e030vboxsync return mMedium->taskCreateDiffHandler(*this);
16a9adc14900ca18e6909679a579f6833425e030vboxsync}
16a9adc14900ca18e6909679a579f6833425e030vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync/**
16a9adc14900ca18e6909679a579f6833425e030vboxsync * Implementation code for the "clone" task.
16a9adc14900ca18e6909679a579f6833425e030vboxsync */
16a9adc14900ca18e6909679a579f6833425e030vboxsyncHRESULT Medium::CloneTask::handler()
16a9adc14900ca18e6909679a579f6833425e030vboxsync{
16a9adc14900ca18e6909679a579f6833425e030vboxsync return mMedium->taskCloneHandler(*this);
16a9adc14900ca18e6909679a579f6833425e030vboxsync}
16a9adc14900ca18e6909679a579f6833425e030vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync/**
16a9adc14900ca18e6909679a579f6833425e030vboxsync * Implementation code for the "compact" task.
16a9adc14900ca18e6909679a579f6833425e030vboxsync */
16a9adc14900ca18e6909679a579f6833425e030vboxsyncHRESULT Medium::CompactTask::handler()
16a9adc14900ca18e6909679a579f6833425e030vboxsync{
16a9adc14900ca18e6909679a579f6833425e030vboxsync return mMedium->taskCompactHandler(*this);
16a9adc14900ca18e6909679a579f6833425e030vboxsync}
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync/**
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync * Implementation code for the "reset" task.
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync */
975ad9d9bc9c4dc96b41d9f67a65228b1b338e2avboxsyncHRESULT Medium::ResetTask::handler()
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync{
975ad9d9bc9c4dc96b41d9f67a65228b1b338e2avboxsync return mMedium->taskResetHandler(*this);
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync}
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync
975ad9d9bc9c4dc96b41d9f67a65228b1b338e2avboxsync/**
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync * Implementation code for the "delete" task.
975ad9d9bc9c4dc96b41d9f67a65228b1b338e2avboxsync */
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsyncHRESULT Medium::DeleteTask::handler()
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync{
975ad9d9bc9c4dc96b41d9f67a65228b1b338e2avboxsync return mMedium->taskDeleteHandler(*this);
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync}
975ad9d9bc9c4dc96b41d9f67a65228b1b338e2avboxsync
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync/**
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync * Implementation code for the "merge" task.
baacecc94a2d23b6f5086739c08cf06d6b357d0avboxsync */
baacecc94a2d23b6f5086739c08cf06d6b357d0avboxsyncHRESULT Medium::MergeTask::handler()
baacecc94a2d23b6f5086739c08cf06d6b357d0avboxsync{
baacecc94a2d23b6f5086739c08cf06d6b357d0avboxsync return mMedium->taskMergeHandler(*this);
baacecc94a2d23b6f5086739c08cf06d6b357d0avboxsync}
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync
c5abe3ea9c7ac6dec34f42af30612534bea951ffvboxsync
c5abe3ea9c7ac6dec34f42af30612534bea951ffvboxsync////////////////////////////////////////////////////////////////////////////////
c5abe3ea9c7ac6dec34f42af30612534bea951ffvboxsync//
c5abe3ea9c7ac6dec34f42af30612534bea951ffvboxsync// Medium constructor / destructor
c5abe3ea9c7ac6dec34f42af30612534bea951ffvboxsync//
1741b757f7a570a7e6d48db46c3f4cd50f2ee296vboxsync////////////////////////////////////////////////////////////////////////////////
1741b757f7a570a7e6d48db46c3f4cd50f2ee296vboxsync
1741b757f7a570a7e6d48db46c3f4cd50f2ee296vboxsyncDEFINE_EMPTY_CTOR_DTOR(Medium)
1741b757f7a570a7e6d48db46c3f4cd50f2ee296vboxsync
c5abe3ea9c7ac6dec34f42af30612534bea951ffvboxsyncHRESULT Medium::FinalConstruct()
c5abe3ea9c7ac6dec34f42af30612534bea951ffvboxsync{
c5abe3ea9c7ac6dec34f42af30612534bea951ffvboxsync m = new Data;
c5abe3ea9c7ac6dec34f42af30612534bea951ffvboxsync
c5abe3ea9c7ac6dec34f42af30612534bea951ffvboxsync /* Initialize the callbacks of the VD error interface */
c5abe3ea9c7ac6dec34f42af30612534bea951ffvboxsync m->vdIfCallsError.cbSize = sizeof(VDINTERFACEERROR);
c5abe3ea9c7ac6dec34f42af30612534bea951ffvboxsync m->vdIfCallsError.enmInterface = VDINTERFACETYPE_ERROR;
c5abe3ea9c7ac6dec34f42af30612534bea951ffvboxsync m->vdIfCallsError.pfnError = vdErrorCall;
c5abe3ea9c7ac6dec34f42af30612534bea951ffvboxsync m->vdIfCallsError.pfnMessage = NULL;
c5abe3ea9c7ac6dec34f42af30612534bea951ffvboxsync
c5abe3ea9c7ac6dec34f42af30612534bea951ffvboxsync /* Initialize the callbacks of the VD config interface */
c5abe3ea9c7ac6dec34f42af30612534bea951ffvboxsync m->vdIfCallsConfig.cbSize = sizeof(VDINTERFACECONFIG);
c5abe3ea9c7ac6dec34f42af30612534bea951ffvboxsync m->vdIfCallsConfig.enmInterface = VDINTERFACETYPE_CONFIG;
c5abe3ea9c7ac6dec34f42af30612534bea951ffvboxsync m->vdIfCallsConfig.pfnAreKeysValid = vdConfigAreKeysValid;
c5abe3ea9c7ac6dec34f42af30612534bea951ffvboxsync m->vdIfCallsConfig.pfnQuerySize = vdConfigQuerySize;
c5abe3ea9c7ac6dec34f42af30612534bea951ffvboxsync m->vdIfCallsConfig.pfnQuery = vdConfigQuery;
c5abe3ea9c7ac6dec34f42af30612534bea951ffvboxsync
1741b757f7a570a7e6d48db46c3f4cd50f2ee296vboxsync /* Initialize the callbacks of the VD TCP interface (we always use the host
1741b757f7a570a7e6d48db46c3f4cd50f2ee296vboxsync * IP stack for now) */
1741b757f7a570a7e6d48db46c3f4cd50f2ee296vboxsync m->vdIfCallsTcpNet.cbSize = sizeof(VDINTERFACETCPNET);
1741b757f7a570a7e6d48db46c3f4cd50f2ee296vboxsync m->vdIfCallsTcpNet.enmInterface = VDINTERFACETYPE_TCPNET;
1741b757f7a570a7e6d48db46c3f4cd50f2ee296vboxsync m->vdIfCallsTcpNet.pfnClientConnect = RTTcpClientConnect;
1741b757f7a570a7e6d48db46c3f4cd50f2ee296vboxsync m->vdIfCallsTcpNet.pfnClientClose = RTTcpClientClose;
d1aab951b0bd1de1a8a51daca46fce06daaed8d7vboxsync m->vdIfCallsTcpNet.pfnSelectOne = RTTcpSelectOne;
d1aab951b0bd1de1a8a51daca46fce06daaed8d7vboxsync m->vdIfCallsTcpNet.pfnRead = RTTcpRead;
d1aab951b0bd1de1a8a51daca46fce06daaed8d7vboxsync m->vdIfCallsTcpNet.pfnWrite = RTTcpWrite;
d1aab951b0bd1de1a8a51daca46fce06daaed8d7vboxsync m->vdIfCallsTcpNet.pfnSgWrite = RTTcpSgWrite;
d1aab951b0bd1de1a8a51daca46fce06daaed8d7vboxsync m->vdIfCallsTcpNet.pfnFlush = RTTcpFlush;
d1aab951b0bd1de1a8a51daca46fce06daaed8d7vboxsync m->vdIfCallsTcpNet.pfnSetSendCoalescing = RTTcpSetSendCoalescing;
d1aab951b0bd1de1a8a51daca46fce06daaed8d7vboxsync m->vdIfCallsTcpNet.pfnGetLocalAddress = RTTcpGetLocalAddress;
d1aab951b0bd1de1a8a51daca46fce06daaed8d7vboxsync m->vdIfCallsTcpNet.pfnGetPeerAddress = RTTcpGetPeerAddress;
d1aab951b0bd1de1a8a51daca46fce06daaed8d7vboxsync
d1aab951b0bd1de1a8a51daca46fce06daaed8d7vboxsync /* Initialize the per-disk interface chain */
d1aab951b0bd1de1a8a51daca46fce06daaed8d7vboxsync int vrc;
d1aab951b0bd1de1a8a51daca46fce06daaed8d7vboxsync vrc = VDInterfaceAdd(&m->vdIfError,
d1aab951b0bd1de1a8a51daca46fce06daaed8d7vboxsync "Medium::vdInterfaceError",
d1aab951b0bd1de1a8a51daca46fce06daaed8d7vboxsync VDINTERFACETYPE_ERROR,
d1aab951b0bd1de1a8a51daca46fce06daaed8d7vboxsync &m->vdIfCallsError, this, &m->vdDiskIfaces);
d1aab951b0bd1de1a8a51daca46fce06daaed8d7vboxsync AssertRCReturn(vrc, E_FAIL);
d1aab951b0bd1de1a8a51daca46fce06daaed8d7vboxsync
d1aab951b0bd1de1a8a51daca46fce06daaed8d7vboxsync vrc = VDInterfaceAdd(&m->vdIfConfig,
d1aab951b0bd1de1a8a51daca46fce06daaed8d7vboxsync "Medium::vdInterfaceConfig",
d1aab951b0bd1de1a8a51daca46fce06daaed8d7vboxsync VDINTERFACETYPE_CONFIG,
d1aab951b0bd1de1a8a51daca46fce06daaed8d7vboxsync &m->vdIfCallsConfig, this, &m->vdDiskIfaces);
d1aab951b0bd1de1a8a51daca46fce06daaed8d7vboxsync AssertRCReturn(vrc, E_FAIL);
d1aab951b0bd1de1a8a51daca46fce06daaed8d7vboxsync
d1aab951b0bd1de1a8a51daca46fce06daaed8d7vboxsync vrc = VDInterfaceAdd(&m->vdIfTcpNet,
d1aab951b0bd1de1a8a51daca46fce06daaed8d7vboxsync "Medium::vdInterfaceTcpNet",
d1aab951b0bd1de1a8a51daca46fce06daaed8d7vboxsync VDINTERFACETYPE_TCPNET,
d1aab951b0bd1de1a8a51daca46fce06daaed8d7vboxsync &m->vdIfCallsTcpNet, this, &m->vdDiskIfaces);
d1aab951b0bd1de1a8a51daca46fce06daaed8d7vboxsync AssertRCReturn(vrc, E_FAIL);
efff36b306e370346025647a158689021df2e1d1vboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync vrc = RTSemEventMultiCreate(&m->queryInfoSem);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync AssertRCReturn(vrc, E_FAIL);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync vrc = RTSemEventMultiSignal(m->queryInfoSem);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync AssertRCReturn(vrc, E_FAIL);
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync
1e9e76e4273dcc2e3d560a0f3605c46f0013eb7bvboxsync return S_OK;
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync}
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsyncvoid Medium::FinalRelease()
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync{
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync uninit();
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync delete m;
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync}
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync/**
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync * Initializes the hard disk object without creating or opening an associated
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync * storage unit.
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync *
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync * For hard disks that don't have the VD_CAP_CREATE_FIXED or
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync * VD_CAP_CREATE_DYNAMIC capability (and therefore cannot be created or deleted
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync * with the means of VirtualBox) the associated storage unit is assumed to be
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync * ready for use so the state of the hard disk object will be set to Created.
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync *
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync * @param aVirtualBox VirtualBox object.
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync * @param aLocation Storage unit location.
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync * @param pfNeedsSaveSettings Optional pointer to a bool that must have been initialized to false and that will be set to true
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync * by this function if the caller should invoke VirtualBox::saveSettings() because the global settings have changed.
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsyncHRESULT Medium::init(VirtualBox *aVirtualBox,
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync CBSTR aFormat,
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync CBSTR aLocation,
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync bool *pfNeedsSaveSettings)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync{
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync AssertReturn(aVirtualBox != NULL, E_FAIL);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync AssertReturn(aFormat != NULL && *aFormat != '\0', E_FAIL);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /* Enclose the state transition NotReady->InInit->Ready */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync AutoInitSpan autoInitSpan(this);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync AssertReturn(autoInitSpan.isOk(), E_FAIL);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync HRESULT rc = S_OK;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /* share VirtualBox weakly (parent remains NULL so far) */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync unconst(m->pVirtualBox) = aVirtualBox;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /* no storage yet */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync m->state = MediumState_NotCreated;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /* cannot be a host drive */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync m->hostDrive = false;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /* No storage unit is created yet, no need to queryInfo() */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync rc = setFormat(aFormat);
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync if (FAILED(rc)) return rc;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
d8c1ea9ddf56bd31af2c314604613d9d695f6e89vboxsync if (m->formatObj->capabilities() & MediumFormatCapabilities_File)
d8c1ea9ddf56bd31af2c314604613d9d695f6e89vboxsync {
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync rc = setLocation(aLocation);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync if (FAILED(rc)) return rc;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync }
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync else
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync {
1e9e76e4273dcc2e3d560a0f3605c46f0013eb7bvboxsync rc = setLocation(aLocation);
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync if (FAILED(rc)) return rc;
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync }
1e9e76e4273dcc2e3d560a0f3605c46f0013eb7bvboxsync
d8c1ea9ddf56bd31af2c314604613d9d695f6e89vboxsync if (!(m->formatObj->capabilities() & ( MediumFormatCapabilities_CreateFixed
d8c1ea9ddf56bd31af2c314604613d9d695f6e89vboxsync | MediumFormatCapabilities_CreateDynamic))
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync )
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync {
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync /* storage for hard disks of this format can neither be explicitly
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync * created by VirtualBox nor deleted, so we place the hard disk to
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync * Created state here and also add it to the registry */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync m->state = MediumState_Created;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync unconst(m->id).create();
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync AutoWriteLock treeLock(m->pVirtualBox->getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS);
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync rc = m->pVirtualBox->registerHardDisk(this, pfNeedsSaveSettings);
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync }
1e9e76e4273dcc2e3d560a0f3605c46f0013eb7bvboxsync
1e9e76e4273dcc2e3d560a0f3605c46f0013eb7bvboxsync /* Confirm a successful initialization when it's the case */
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync if (SUCCEEDED(rc))
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync autoInitSpan.setSucceeded();
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync return rc;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync}
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync/**
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync * Initializes the medium object by opening the storage unit at the specified
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync * location. The enOpenMode parameter defines whether the image will be opened
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync * read/write or read-only.
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync *
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync * Note that the UUID, format and the parent of this medium will be
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync * determined when reading the medium storage unit, unless new values are
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync * specified by the parameters. If the detected or set parent is
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync * not known to VirtualBox, then this method will fail.
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync *
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync * @param aVirtualBox VirtualBox object.
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync * @param aLocation Storage unit location.
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync * @param enOpenMode Whether to open the image read/write or read-only.
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync * @param aDeviceType Device type of medium.
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync * @param aSetImageId Whether to set the image UUID or not.
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync * @param aImageId New image UUID if @aSetId is true. Empty string means
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync * create a new UUID, and a zero UUID is invalid.
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync * @param aSetParentId Whether to set the parent UUID or not.
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync * @param aParentId New parent UUID if @aSetParentId is true. Empty string
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync * means create a new UUID, and a zero UUID is valid.
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync */
30c39307775310ba50de9d9b74f1ea9e12524102vboxsyncHRESULT Medium::init(VirtualBox *aVirtualBox,
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync CBSTR aLocation,
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync HDDOpenMode enOpenMode,
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync DeviceType_T aDeviceType,
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync BOOL aSetImageId,
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync const Guid &aImageId,
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync BOOL aSetParentId,
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync const Guid &aParentId)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync{
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync AssertReturn(aVirtualBox, E_INVALIDARG);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync AssertReturn(aLocation, E_INVALIDARG);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync /* Enclose the state transition NotReady->InInit->Ready */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync AutoInitSpan autoInitSpan(this);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync AssertReturn(autoInitSpan.isOk(), E_FAIL);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync HRESULT rc = S_OK;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /* share VirtualBox weakly (parent remains NULL so far) */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync unconst(m->pVirtualBox) = aVirtualBox;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /* there must be a storage unit */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync m->state = MediumState_Created;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync /* remember device type for correct unregistering later */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync m->devType = aDeviceType;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /* cannot be a host drive */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync m->hostDrive = false;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /* remember the open mode (defaults to ReadWrite) */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync m->hddOpenMode = enOpenMode;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (aDeviceType == DeviceType_HardDisk)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync rc = setLocation(aLocation);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync else
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync rc = setLocation(aLocation, "RAW");
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync if (FAILED(rc)) return rc;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync /* save the new uuid values, will be used by queryInfo() */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync m->setImageId = !!aSetImageId;
251b3801f86afc901bee955a7e5a8d14b5836e74vboxsync unconst(m->imageId) = aImageId;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync m->setParentId = !!aSetParentId;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync unconst(m->parentId) = aParentId;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync /* get all the information about the medium from the storage unit */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync rc = queryInfo();
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync if (SUCCEEDED(rc))
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync {
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync /* if the storage unit is not accessible, it's not acceptable for the
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync * newly opened media so convert this into an error */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (m->state == MediumState_Inaccessible)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync {
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync Assert(!m->strLastAccessError.isEmpty());
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync rc = setError(E_FAIL, m->strLastAccessError.c_str());
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync }
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync else
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync {
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync AssertReturn(!m->id.isEmpty(), E_FAIL);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync /* storage format must be detected by queryInfo() if the medium is accessible */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync AssertReturn(!m->strFormat.isEmpty(), E_FAIL);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync }
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync }
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync /* Confirm a successful initialization when it's the case */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync if (SUCCEEDED(rc))
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync autoInitSpan.setSucceeded();
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync return rc;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync}
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync/**
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync * Initializes the medium object by loading its data from the given settings
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync * node. In this mode, the image will always be opened read/write.
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync *
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync * @param aVirtualBox VirtualBox object.
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync * @param aParent Parent medium disk or NULL for a root (base) medium.
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync * @param aDeviceType Device type of the medium.
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync * @param aNode Configuration settings.
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync *
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync * @note Locks VirtualBox for writing, the medium tree for writing.
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsyncHRESULT Medium::init(VirtualBox *aVirtualBox,
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync Medium *aParent,
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync DeviceType_T aDeviceType,
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync const settings::Medium &data)
59a2c1c0a4a0762b46bc5ff056f5705ec9c0a660vboxsync{
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync using namespace settings;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync AssertReturn(aVirtualBox, E_INVALIDARG);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync /* Enclose the state transition NotReady->InInit->Ready */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync AutoInitSpan autoInitSpan(this);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync AssertReturn(autoInitSpan.isOk(), E_FAIL);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync HRESULT rc = S_OK;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync /* share VirtualBox and parent weakly */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync unconst(m->pVirtualBox) = aVirtualBox;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync /* register with VirtualBox/parent early, since uninit() will
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync * unconditionally unregister on failure */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync if (aParent)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync {
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync // differencing image: add to parent
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync AutoWriteLock treeLock(m->pVirtualBox->getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync m->pParent = aParent;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync aParent->m->llChildren.push_back(this);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync }
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /* see below why we don't call queryInfo() (and therefore treat the medium
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync * as inaccessible for now */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync m->state = MediumState_Inaccessible;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync m->strLastAccessError = tr("Accessibility check was not yet performed");
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync /* required */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync unconst(m->id) = data.uuid;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /* assume not a host drive */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync m->hostDrive = false;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync /* optional */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync m->strDescription = data.strDescription;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync /* required */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync if (aDeviceType == DeviceType_HardDisk)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync {
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync AssertReturn(!data.strFormat.isEmpty(), E_FAIL);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync rc = setFormat(Bstr(data.strFormat));
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync if (FAILED(rc)) return rc;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync }
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync else
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync {
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync /// @todo handle host drive settings here as well?
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync if (!data.strFormat.isEmpty())
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync rc = setFormat(Bstr(data.strFormat));
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync else
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync rc = setFormat(Bstr("RAW"));
4bd3e7685494afe7c303fc131c66e685023b6b4avboxsync if (FAILED(rc)) return rc;
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync }
4bd3e7685494afe7c303fc131c66e685023b6b4avboxsync
4bd3e7685494afe7c303fc131c66e685023b6b4avboxsync /* optional, only for diffs, default is false;
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync * we can only auto-reset diff images, so they
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync * must not have a parent */
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync if (aParent != NULL)
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync m->autoReset = data.fAutoReset;
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync else
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync m->autoReset = false;
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync /* properties (after setting the format as it populates the map). Note that
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync * if some properties are not supported but preseint in the settings file,
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync * they will still be read and accessible (for possible backward
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync * compatibility; we can also clean them up from the XML upon next
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync * XML format version change if we wish) */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync for (settings::PropertiesMap::const_iterator it = data.properties.begin();
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync it != data.properties.end(); ++it)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync {
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync const Utf8Str &name = it->first;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync const Utf8Str &value = it->second;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync m->properties[Bstr(name)] = Bstr(value);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync }
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync /* required */
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync rc = setLocation(data.strLocation);
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync if (FAILED(rc)) return rc;
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (aDeviceType == DeviceType_HardDisk)
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync {
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /* type is only for base hard disks */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (m->pParent.isNull())
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync m->type = data.hdType;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync }
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync else
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync m->type = MediumType_Writethrough;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync /* remember device type for correct unregistering later */
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync m->devType = aDeviceType;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync LogFlowThisFunc(("m->strLocationFull='%s', m->strFormat=%s, m->id={%RTuuid}\n",
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync m->strLocationFull.raw(), m->strFormat.raw(), m->id.raw()));
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync /* Don't call queryInfo() for registered media to prevent the calling
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync * thread (i.e. the VirtualBox server startup thread) from an unexpected
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync * freeze but mark it as initially inaccessible instead. The vital UUID,
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync * location and format properties are read from the registry file above; to
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync * get the actual state and the rest of the data, the user will have to call
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync * COMGETTER(State). */
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync AutoWriteLock treeLock(aVirtualBox->getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS);
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync /* load all children */
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync for (settings::MediaList::const_iterator it = data.llChildren.begin();
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync it != data.llChildren.end();
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync ++it)
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync {
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync const settings::Medium &med = *it;
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync ComObjPtr<Medium> pHD;
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync pHD.createObject();
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync rc = pHD->init(aVirtualBox,
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync this, // parent
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync aDeviceType,
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync med); // child data
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync if (FAILED(rc)) break;
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync rc = m->pVirtualBox->registerHardDisk(pHD, NULL /*pfNeedsSaveSettings*/);
a0a3a26a4065b9401681a8c99a11bd83e08f94ccvboxsync if (FAILED(rc)) break;
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync }
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync /* Confirm a successful initialization when it's the case */
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync if (SUCCEEDED(rc))
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync autoInitSpan.setSucceeded();
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync return rc;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync}
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync/**
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync * Initializes the medium object by providing the host drive information.
8dbf70ba2345e69b0b6d45c38cf1add0ef10591cvboxsync * Not used for anything but the host floppy/host DVD case.
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync *
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync * @todo optimize all callers to avoid reconstructing objects with the same
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync * information over and over again - in the typical case each VM referring to
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync * a particular host drive has its own instance.
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync *
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync * @param aVirtualBox VirtualBox object.
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync * @param aDeviceType Device type of the medium.
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync * @param aLocation Location of the host drive.
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync * @param aDescription Comment for this host drive.
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync *
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync * @note Locks VirtualBox lock for writing.
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync */
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsyncHRESULT Medium::init(VirtualBox *aVirtualBox,
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync DeviceType_T aDeviceType,
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync CBSTR aLocation,
a0a3a26a4065b9401681a8c99a11bd83e08f94ccvboxsync CBSTR aDescription)
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync{
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync ComAssertRet(aDeviceType == DeviceType_DVD || aDeviceType == DeviceType_Floppy, E_INVALIDARG);
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync ComAssertRet(aLocation, E_INVALIDARG);
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync /* Enclose the state transition NotReady->InInit->Ready */
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync AutoInitSpan autoInitSpan(this);
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync AssertReturn(autoInitSpan.isOk(), E_FAIL);
30c39307775310ba50de9d9b74f1ea9e12524102vboxsync
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync /* share VirtualBox weakly (parent remains NULL so far) */
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync unconst(m->pVirtualBox) = aVirtualBox;
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync /* fake up a UUID which is unique, but also reproducible */
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync RTUUID uuid;
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync RTUuidClear(&uuid);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (aDeviceType == DeviceType_DVD)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync memcpy(&uuid.au8[0], "DVD", 3);
51a01524909c95ee04b636218b6a89b29fb81825vboxsync else
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync memcpy(&uuid.au8[0], "FD", 2);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /* use device name, adjusted to the end of uuid, shortened if necessary */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync Utf8Str loc(aLocation);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync size_t cbLocation = strlen(loc.raw());
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (cbLocation > 12)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync memcpy(&uuid.au8[4], loc.raw() + (cbLocation - 12), 12);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync else
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync memcpy(&uuid.au8[4 + 12 - cbLocation], loc.raw(), cbLocation);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync unconst(m->id) = uuid;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync m->type = MediumType_Writethrough;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync m->devType = aDeviceType;
efff36b306e370346025647a158689021df2e1d1vboxsync m->state = MediumState_Created;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync m->hostDrive = true;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync HRESULT rc = setFormat(Bstr("RAW"));
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (FAILED(rc)) return rc;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync rc = setLocation(aLocation);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (FAILED(rc)) return rc;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync m->strDescription = aDescription;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync/// @todo generate uuid (similarly to host network interface uuid) from location and device type
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync autoInitSpan.setSucceeded();
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync return S_OK;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync}
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync/**
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync * Uninitializes the instance.
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync *
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync * Called either from FinalRelease() or by the parent when it gets destroyed.
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync *
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync * @note All children of this hard disk get uninitialized by calling their
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync * uninit() methods.
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync *
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync * @note Caller must hold the tree lock of the medium tree this medium is on.
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync */
51a01524909c95ee04b636218b6a89b29fb81825vboxsyncvoid Medium::uninit()
51a01524909c95ee04b636218b6a89b29fb81825vboxsync{
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /* Enclose the state transition Ready->InUninit->NotReady */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync AutoUninitSpan autoUninitSpan(this);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (autoUninitSpan.uninitDone())
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync return;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (!m->formatObj.isNull())
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync {
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /* remove the caller reference we added in setFormat() */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync m->formatObj->releaseCaller();
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync m->formatObj.setNull();
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync }
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (m->state == MediumState_Deleting)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync {
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /* we are being uninitialized after've been deleted by merge.
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync * Reparenting has already been done so don't touch it here (we are
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync * now orphans and removeDependentChild() will assert) */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync Assert(m->pParent.isNull());
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync }
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync else
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync {
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync MediaList::iterator it;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync for (it = m->llChildren.begin();
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync it != m->llChildren.end();
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync ++it)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync {
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync Medium *pChild = *it;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pChild->m->pParent.setNull();
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pChild->uninit();
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync }
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync m->llChildren.clear(); // this unsets all the ComPtrs and probably calls delete
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (m->pParent)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync {
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync // this is a differencing disk: then remove it from the parent's children list
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync deparent();
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync }
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync }
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync RTSemEventMultiSignal(m->queryInfoSem);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync RTSemEventMultiDestroy(m->queryInfoSem);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync m->queryInfoSem = NIL_RTSEMEVENTMULTI;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync unconst(m->pVirtualBox) = NULL;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync}
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync/**
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync * Internal helper that removes "this" from the list of children of its
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync * parent. Used in uninit() and other places when reparenting is necessary.
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync *
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync * The caller must hold the hard disk tree lock!
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsyncvoid Medium::deparent()
b0b15690f00527424b2d5fb88456d747252322f7vboxsync{
b0b15690f00527424b2d5fb88456d747252322f7vboxsync MediaList &llParent = m->pParent->m->llChildren;
b0b15690f00527424b2d5fb88456d747252322f7vboxsync for (MediaList::iterator it = llParent.begin();
b0b15690f00527424b2d5fb88456d747252322f7vboxsync it != llParent.end();
b0b15690f00527424b2d5fb88456d747252322f7vboxsync ++it)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync {
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync Medium *pParentsChild = *it;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (this == pParentsChild)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync {
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync llParent.erase(it);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync break;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync }
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync }
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync m->pParent.setNull();
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync}
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync/**
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync * Internal helper that removes "this" from the list of children of its
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync * parent. Used in uninit() and other places when reparenting is necessary.
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync *
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync * The caller must hold the hard disk tree lock!
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsyncvoid Medium::setParent(const ComObjPtr<Medium> &pParent)
b0b15690f00527424b2d5fb88456d747252322f7vboxsync{
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync m->pParent = pParent;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (pParent)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync pParent->m->llChildren.push_back(this);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync}
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync////////////////////////////////////////////////////////////////////////////////
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync//
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync// IMedium public methods
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync//
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync////////////////////////////////////////////////////////////////////////////////
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
a2f96875f61628e5a5fd33785f8c0bbb310f981fvboxsyncSTDMETHODIMP Medium::COMGETTER(Id)(BSTR *aId)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync{
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync CheckComArgOutPointerValid(aId);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync AutoCaller autoCaller(this);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
d8c1ea9ddf56bd31af2c314604613d9d695f6e89vboxsync
d8c1ea9ddf56bd31af2c314604613d9d695f6e89vboxsync m->id.toUtf16().cloneTo(aId);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync return S_OK;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync}
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
d8c1ea9ddf56bd31af2c314604613d9d695f6e89vboxsyncSTDMETHODIMP Medium::COMGETTER(Description)(BSTR *aDescription)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync{
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync CheckComArgOutPointerValid(aDescription);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync AutoCaller autoCaller(this);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
51a01524909c95ee04b636218b6a89b29fb81825vboxsync
51a01524909c95ee04b636218b6a89b29fb81825vboxsync AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
51a01524909c95ee04b636218b6a89b29fb81825vboxsync m->strDescription.cloneTo(aDescription);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync return S_OK;
b0b15690f00527424b2d5fb88456d747252322f7vboxsync}
b0b15690f00527424b2d5fb88456d747252322f7vboxsync
b0b15690f00527424b2d5fb88456d747252322f7vboxsyncSTDMETHODIMP Medium::COMSETTER(Description)(IN_BSTR aDescription)
a2f96875f61628e5a5fd33785f8c0bbb310f981fvboxsync{
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync AutoCaller autoCaller(this);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync// AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /// @todo update m->description and save the global registry (and local
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /// registries of portable VMs referring to this medium), this will also
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /// require to add the mRegistered flag to data
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync NOREF(aDescription);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync ReturnComNotImplemented();
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync}
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsyncSTDMETHODIMP Medium::COMGETTER(State)(MediumState_T *aState)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync{
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync CheckComArgOutPointerValid(aState);
a2f96875f61628e5a5fd33785f8c0bbb310f981fvboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync AutoCaller autoCaller(this);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync *aState = m->state;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync return S_OK;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync}
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsyncSTDMETHODIMP Medium::COMGETTER(Location)(BSTR *aLocation)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync{
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync CheckComArgOutPointerValid(aLocation);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync AutoCaller autoCaller(this);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync m->strLocationFull.cloneTo(aLocation);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync return S_OK;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync}
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsyncSTDMETHODIMP Medium::COMSETTER(Location)(IN_BSTR aLocation)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync{
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync CheckComArgStrNotEmptyOrNull(aLocation);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync AutoCaller autoCaller(this);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /// @todo NEWMEDIA for file names, add the default extension if no extension
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /// is present (using the information from the VD backend which also implies
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /// that one more parameter should be passed to setLocation() requesting
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /// that functionality since it is only allwed when called from this method
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /// @todo NEWMEDIA rename the file and set m->location on success, then save
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /// the global registry (and local registries of portable VMs referring to
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /// this medium), this will also require to add the mRegistered flag to data
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync ReturnComNotImplemented();
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync}
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
51a01524909c95ee04b636218b6a89b29fb81825vboxsyncSTDMETHODIMP Medium::COMGETTER(Name)(BSTR *aName)
51a01524909c95ee04b636218b6a89b29fb81825vboxsync{
51a01524909c95ee04b636218b6a89b29fb81825vboxsync CheckComArgOutPointerValid(aName);
51a01524909c95ee04b636218b6a89b29fb81825vboxsync
51a01524909c95ee04b636218b6a89b29fb81825vboxsync AutoCaller autoCaller(this);
51a01524909c95ee04b636218b6a89b29fb81825vboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
51a01524909c95ee04b636218b6a89b29fb81825vboxsync
51a01524909c95ee04b636218b6a89b29fb81825vboxsync AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
51a01524909c95ee04b636218b6a89b29fb81825vboxsync
51a01524909c95ee04b636218b6a89b29fb81825vboxsync getName().cloneTo(aName);
51a01524909c95ee04b636218b6a89b29fb81825vboxsync
51a01524909c95ee04b636218b6a89b29fb81825vboxsync return S_OK;
51a01524909c95ee04b636218b6a89b29fb81825vboxsync}
51a01524909c95ee04b636218b6a89b29fb81825vboxsync
51a01524909c95ee04b636218b6a89b29fb81825vboxsyncSTDMETHODIMP Medium::COMGETTER(DeviceType)(DeviceType_T *aDeviceType)
51a01524909c95ee04b636218b6a89b29fb81825vboxsync{
51a01524909c95ee04b636218b6a89b29fb81825vboxsync CheckComArgOutPointerValid(aDeviceType);
51a01524909c95ee04b636218b6a89b29fb81825vboxsync
51a01524909c95ee04b636218b6a89b29fb81825vboxsync AutoCaller autoCaller(this);
51a01524909c95ee04b636218b6a89b29fb81825vboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
51a01524909c95ee04b636218b6a89b29fb81825vboxsync
51a01524909c95ee04b636218b6a89b29fb81825vboxsync AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
51a01524909c95ee04b636218b6a89b29fb81825vboxsync
51a01524909c95ee04b636218b6a89b29fb81825vboxsync *aDeviceType = m->devType;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync return S_OK;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync}
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsyncSTDMETHODIMP Medium::COMGETTER(HostDrive)(BOOL *aHostDrive)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync{
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync CheckComArgOutPointerValid(aHostDrive);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync AutoCaller autoCaller(this);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync *aHostDrive = m->hostDrive;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync return S_OK;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync}
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsyncSTDMETHODIMP Medium::COMGETTER(Size)(ULONG64 *aSize)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync{
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync CheckComArgOutPointerValid(aSize);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync AutoCaller autoCaller(this);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync *aSize = m->size;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync return S_OK;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync}
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
b0b15690f00527424b2d5fb88456d747252322f7vboxsyncSTDMETHODIMP Medium::COMGETTER(Format)(BSTR *aFormat)
b0b15690f00527424b2d5fb88456d747252322f7vboxsync{
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync CheckComArgOutPointerValid(aFormat);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync AutoCaller autoCaller(this);
51a01524909c95ee04b636218b6a89b29fb81825vboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /* no need to lock, m->strFormat is const */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync m->strFormat.cloneTo(aFormat);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
217fa436516d137a409bb493cb7d350898f64666vboxsync return S_OK;
217fa436516d137a409bb493cb7d350898f64666vboxsync}
51a01524909c95ee04b636218b6a89b29fb81825vboxsync
51a01524909c95ee04b636218b6a89b29fb81825vboxsyncSTDMETHODIMP Medium::COMGETTER(MediumFormat)(IMediumFormat **aMediumFormat)
51a01524909c95ee04b636218b6a89b29fb81825vboxsync{
51a01524909c95ee04b636218b6a89b29fb81825vboxsync CheckComArgOutPointerValid(aMediumFormat);
51a01524909c95ee04b636218b6a89b29fb81825vboxsync
51a01524909c95ee04b636218b6a89b29fb81825vboxsync AutoCaller autoCaller(this);
51a01524909c95ee04b636218b6a89b29fb81825vboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
51a01524909c95ee04b636218b6a89b29fb81825vboxsync
51a01524909c95ee04b636218b6a89b29fb81825vboxsync /* no need to lock, m->formatObj is const */
51a01524909c95ee04b636218b6a89b29fb81825vboxsync m->formatObj.queryInterfaceTo(aMediumFormat);
51a01524909c95ee04b636218b6a89b29fb81825vboxsync
51a01524909c95ee04b636218b6a89b29fb81825vboxsync return S_OK;
51a01524909c95ee04b636218b6a89b29fb81825vboxsync}
51a01524909c95ee04b636218b6a89b29fb81825vboxsync
51a01524909c95ee04b636218b6a89b29fb81825vboxsyncSTDMETHODIMP Medium::COMGETTER(Type)(MediumType_T *aType)
51a01524909c95ee04b636218b6a89b29fb81825vboxsync{
51a01524909c95ee04b636218b6a89b29fb81825vboxsync CheckComArgOutPointerValid(aType);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync AutoCaller autoCaller(this);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync *aType = m->type;
51a01524909c95ee04b636218b6a89b29fb81825vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync return S_OK;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync}
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsyncSTDMETHODIMP Medium::COMSETTER(Type)(MediumType_T aType)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync{
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync AutoCaller autoCaller(this);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
51a01524909c95ee04b636218b6a89b29fb81825vboxsync // we access mParent and members
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync AutoMultiWriteLock2 mlock(&m->pVirtualBox->getMediaTreeLockHandle(), this->lockHandle() COMMA_LOCKVAL_SRC_POS);
51a01524909c95ee04b636218b6a89b29fb81825vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync switch (m->state)
51a01524909c95ee04b636218b6a89b29fb81825vboxsync {
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync case MediumState_Created:
51a01524909c95ee04b636218b6a89b29fb81825vboxsync case MediumState_Inaccessible:
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync break;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync default:
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync return setStateError();
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync }
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /** @todo implement this case later */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync CheckComArgExpr(aType, aType != MediumType_Shareable);
217fa436516d137a409bb493cb7d350898f64666vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (m->type == aType)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync {
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /* Nothing to do */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync return S_OK;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync }
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /* cannot change the type of a differencing hard disk */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (m->pParent)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync return setError(E_FAIL,
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync tr("Cannot change the type of hard disk '%s' because it is a differencing hard disk"),
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync m->strLocationFull.raw());
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync /* cannot change the type of a hard disk being in use by more than one VM */
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (m->backRefs.size() > 1)
b0b15690f00527424b2d5fb88456d747252322f7vboxsync return setError(E_FAIL,
b0b15690f00527424b2d5fb88456d747252322f7vboxsync tr("Cannot change the type of hard disk '%s' because it is attached to %d virtual machines"),
b0b15690f00527424b2d5fb88456d747252322f7vboxsync m->strLocationFull.raw(), m->backRefs.size());
b0b15690f00527424b2d5fb88456d747252322f7vboxsync
b0b15690f00527424b2d5fb88456d747252322f7vboxsync switch (aType)
b0b15690f00527424b2d5fb88456d747252322f7vboxsync {
b0b15690f00527424b2d5fb88456d747252322f7vboxsync case MediumType_Normal:
b0b15690f00527424b2d5fb88456d747252322f7vboxsync case MediumType_Immutable:
b0b15690f00527424b2d5fb88456d747252322f7vboxsync {
b0b15690f00527424b2d5fb88456d747252322f7vboxsync /* normal can be easily converted to immutable and vice versa even
b0b15690f00527424b2d5fb88456d747252322f7vboxsync * if they have children as long as they are not attached to any
b0b15690f00527424b2d5fb88456d747252322f7vboxsync * machine themselves */
b0b15690f00527424b2d5fb88456d747252322f7vboxsync break;
b0b15690f00527424b2d5fb88456d747252322f7vboxsync }
b0b15690f00527424b2d5fb88456d747252322f7vboxsync case MediumType_Writethrough:
b0b15690f00527424b2d5fb88456d747252322f7vboxsync case MediumType_Shareable:
b0b15690f00527424b2d5fb88456d747252322f7vboxsync {
b0b15690f00527424b2d5fb88456d747252322f7vboxsync /* cannot change to writethrough or shareable if there are children */
b0b15690f00527424b2d5fb88456d747252322f7vboxsync if (getChildren().size() != 0)
b0b15690f00527424b2d5fb88456d747252322f7vboxsync return setError(E_FAIL,
b0b15690f00527424b2d5fb88456d747252322f7vboxsync tr("Cannot change type for hard disk '%s' since it has %d child hard disk(s)"),
b0b15690f00527424b2d5fb88456d747252322f7vboxsync m->strLocationFull.raw(), getChildren().size());
b0b15690f00527424b2d5fb88456d747252322f7vboxsync break;
b0b15690f00527424b2d5fb88456d747252322f7vboxsync }
b0b15690f00527424b2d5fb88456d747252322f7vboxsync default:
b0b15690f00527424b2d5fb88456d747252322f7vboxsync AssertFailedReturn(E_FAIL);
b0b15690f00527424b2d5fb88456d747252322f7vboxsync }
b0b15690f00527424b2d5fb88456d747252322f7vboxsync
b0b15690f00527424b2d5fb88456d747252322f7vboxsync m->type = aType;
b0b15690f00527424b2d5fb88456d747252322f7vboxsync
b0b15690f00527424b2d5fb88456d747252322f7vboxsync mlock.release();
b0b15690f00527424b2d5fb88456d747252322f7vboxsync
b0b15690f00527424b2d5fb88456d747252322f7vboxsync // saveSettings needs vbox lock
b0b15690f00527424b2d5fb88456d747252322f7vboxsync AutoWriteLock alock(m->pVirtualBox COMMA_LOCKVAL_SRC_POS);
b0b15690f00527424b2d5fb88456d747252322f7vboxsync
b0b15690f00527424b2d5fb88456d747252322f7vboxsync HRESULT rc = m->pVirtualBox->saveSettings();
b0b15690f00527424b2d5fb88456d747252322f7vboxsync
b0b15690f00527424b2d5fb88456d747252322f7vboxsync return rc;
b0b15690f00527424b2d5fb88456d747252322f7vboxsync}
b0b15690f00527424b2d5fb88456d747252322f7vboxsync
b0b15690f00527424b2d5fb88456d747252322f7vboxsyncSTDMETHODIMP Medium::COMGETTER(Parent)(IMedium **aParent)
b0b15690f00527424b2d5fb88456d747252322f7vboxsync{
b0b15690f00527424b2d5fb88456d747252322f7vboxsync CheckComArgOutPointerValid(aParent);
b0b15690f00527424b2d5fb88456d747252322f7vboxsync
b0b15690f00527424b2d5fb88456d747252322f7vboxsync AutoCaller autoCaller(this);
b0b15690f00527424b2d5fb88456d747252322f7vboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
b0b15690f00527424b2d5fb88456d747252322f7vboxsync
b0b15690f00527424b2d5fb88456d747252322f7vboxsync /* we access mParent */
b0b15690f00527424b2d5fb88456d747252322f7vboxsync AutoReadLock treeLock(m->pVirtualBox->getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS);
b0b15690f00527424b2d5fb88456d747252322f7vboxsync
b0b15690f00527424b2d5fb88456d747252322f7vboxsync m->pParent.queryInterfaceTo(aParent);
b0b15690f00527424b2d5fb88456d747252322f7vboxsync
b0b15690f00527424b2d5fb88456d747252322f7vboxsync return S_OK;
b0b15690f00527424b2d5fb88456d747252322f7vboxsync}
b0b15690f00527424b2d5fb88456d747252322f7vboxsync
b0b15690f00527424b2d5fb88456d747252322f7vboxsyncSTDMETHODIMP Medium::COMGETTER(Children)(ComSafeArrayOut(IMedium *, aChildren))
b0b15690f00527424b2d5fb88456d747252322f7vboxsync{
b0b15690f00527424b2d5fb88456d747252322f7vboxsync CheckComArgOutSafeArrayPointerValid(aChildren);
b0b15690f00527424b2d5fb88456d747252322f7vboxsync
b0b15690f00527424b2d5fb88456d747252322f7vboxsync AutoCaller autoCaller(this);
b0b15690f00527424b2d5fb88456d747252322f7vboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
b0b15690f00527424b2d5fb88456d747252322f7vboxsync
b0b15690f00527424b2d5fb88456d747252322f7vboxsync /* we access children */
b0b15690f00527424b2d5fb88456d747252322f7vboxsync AutoReadLock treeLock(m->pVirtualBox->getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS);
b0b15690f00527424b2d5fb88456d747252322f7vboxsync
b0b15690f00527424b2d5fb88456d747252322f7vboxsync SafeIfaceArray<IMedium> children(this->getChildren());
b0b15690f00527424b2d5fb88456d747252322f7vboxsync children.detachTo(ComSafeArrayOutArg(aChildren));
b0b15690f00527424b2d5fb88456d747252322f7vboxsync
b0b15690f00527424b2d5fb88456d747252322f7vboxsync return S_OK;
b0b15690f00527424b2d5fb88456d747252322f7vboxsync}
b0b15690f00527424b2d5fb88456d747252322f7vboxsync
b0b15690f00527424b2d5fb88456d747252322f7vboxsyncSTDMETHODIMP Medium::COMGETTER(Base)(IMedium **aBase)
b0b15690f00527424b2d5fb88456d747252322f7vboxsync{
b0b15690f00527424b2d5fb88456d747252322f7vboxsync CheckComArgOutPointerValid(aBase);
b0b15690f00527424b2d5fb88456d747252322f7vboxsync
b0b15690f00527424b2d5fb88456d747252322f7vboxsync /* base() will do callers/locking */
b0b15690f00527424b2d5fb88456d747252322f7vboxsync
b0b15690f00527424b2d5fb88456d747252322f7vboxsync getBase().queryInterfaceTo(aBase);
b0b15690f00527424b2d5fb88456d747252322f7vboxsync
b0b15690f00527424b2d5fb88456d747252322f7vboxsync return S_OK;
b0b15690f00527424b2d5fb88456d747252322f7vboxsync}
b0b15690f00527424b2d5fb88456d747252322f7vboxsync
b0b15690f00527424b2d5fb88456d747252322f7vboxsyncSTDMETHODIMP Medium::COMGETTER(ReadOnly)(BOOL *aReadOnly)
b0b15690f00527424b2d5fb88456d747252322f7vboxsync{
b0b15690f00527424b2d5fb88456d747252322f7vboxsync CheckComArgOutPointerValid(aReadOnly);
b0b15690f00527424b2d5fb88456d747252322f7vboxsync
b0b15690f00527424b2d5fb88456d747252322f7vboxsync AutoCaller autoCaller(this);
b0b15690f00527424b2d5fb88456d747252322f7vboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
b0b15690f00527424b2d5fb88456d747252322f7vboxsync
b0b15690f00527424b2d5fb88456d747252322f7vboxsync /* isRadOnly() will do locking */
b0b15690f00527424b2d5fb88456d747252322f7vboxsync
b0b15690f00527424b2d5fb88456d747252322f7vboxsync *aReadOnly = isReadOnly();
b0b15690f00527424b2d5fb88456d747252322f7vboxsync
b0b15690f00527424b2d5fb88456d747252322f7vboxsync return S_OK;
b0b15690f00527424b2d5fb88456d747252322f7vboxsync}
b0b15690f00527424b2d5fb88456d747252322f7vboxsync
b0b15690f00527424b2d5fb88456d747252322f7vboxsyncSTDMETHODIMP Medium::COMGETTER(LogicalSize)(ULONG64 *aLogicalSize)
b0b15690f00527424b2d5fb88456d747252322f7vboxsync{
b0b15690f00527424b2d5fb88456d747252322f7vboxsync CheckComArgOutPointerValid(aLogicalSize);
b0b15690f00527424b2d5fb88456d747252322f7vboxsync
b0b15690f00527424b2d5fb88456d747252322f7vboxsync {
b0b15690f00527424b2d5fb88456d747252322f7vboxsync AutoCaller autoCaller(this);
b0b15690f00527424b2d5fb88456d747252322f7vboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
b0b15690f00527424b2d5fb88456d747252322f7vboxsync
b0b15690f00527424b2d5fb88456d747252322f7vboxsync /* we access mParent */
b0b15690f00527424b2d5fb88456d747252322f7vboxsync AutoReadLock treeLock(m->pVirtualBox->getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS);
b0b15690f00527424b2d5fb88456d747252322f7vboxsync
b0b15690f00527424b2d5fb88456d747252322f7vboxsync AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
b0b15690f00527424b2d5fb88456d747252322f7vboxsync
b0b15690f00527424b2d5fb88456d747252322f7vboxsync if (m->pParent.isNull())
b0b15690f00527424b2d5fb88456d747252322f7vboxsync {
b0b15690f00527424b2d5fb88456d747252322f7vboxsync *aLogicalSize = m->logicalSize;
b0b15690f00527424b2d5fb88456d747252322f7vboxsync
b0b15690f00527424b2d5fb88456d747252322f7vboxsync return S_OK;
b0b15690f00527424b2d5fb88456d747252322f7vboxsync }
b0b15690f00527424b2d5fb88456d747252322f7vboxsync }
b0b15690f00527424b2d5fb88456d747252322f7vboxsync
b0b15690f00527424b2d5fb88456d747252322f7vboxsync /* We assume that some backend may decide to return a meaningless value in
b0b15690f00527424b2d5fb88456d747252322f7vboxsync * response to VDGetSize() for differencing hard disks and therefore
b0b15690f00527424b2d5fb88456d747252322f7vboxsync * always ask the base hard disk ourselves. */
b0b15690f00527424b2d5fb88456d747252322f7vboxsync
b0b15690f00527424b2d5fb88456d747252322f7vboxsync /* base() will do callers/locking */
b0b15690f00527424b2d5fb88456d747252322f7vboxsync
b0b15690f00527424b2d5fb88456d747252322f7vboxsync return getBase()->COMGETTER(LogicalSize)(aLogicalSize);
b0b15690f00527424b2d5fb88456d747252322f7vboxsync}
b0b15690f00527424b2d5fb88456d747252322f7vboxsync
b0b15690f00527424b2d5fb88456d747252322f7vboxsyncSTDMETHODIMP Medium::COMGETTER(AutoReset)(BOOL *aAutoReset)
b0b15690f00527424b2d5fb88456d747252322f7vboxsync{
b0b15690f00527424b2d5fb88456d747252322f7vboxsync CheckComArgOutPointerValid(aAutoReset);
b0b15690f00527424b2d5fb88456d747252322f7vboxsync
b0b15690f00527424b2d5fb88456d747252322f7vboxsync AutoCaller autoCaller(this);
b0b15690f00527424b2d5fb88456d747252322f7vboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
b0b15690f00527424b2d5fb88456d747252322f7vboxsync
b0b15690f00527424b2d5fb88456d747252322f7vboxsync AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
b0b15690f00527424b2d5fb88456d747252322f7vboxsync
b0b15690f00527424b2d5fb88456d747252322f7vboxsync if (m->pParent)
b0b15690f00527424b2d5fb88456d747252322f7vboxsync *aAutoReset = FALSE;
b0b15690f00527424b2d5fb88456d747252322f7vboxsync else
b0b15690f00527424b2d5fb88456d747252322f7vboxsync *aAutoReset = m->autoReset;
b0b15690f00527424b2d5fb88456d747252322f7vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync return S_OK;
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync}
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsyncSTDMETHODIMP Medium::COMSETTER(AutoReset)(BOOL aAutoReset)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync{
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync AutoCaller autoCaller(this);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync AutoWriteLock mlock(this COMMA_LOCKVAL_SRC_POS);
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (m->pParent.isNull())
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync return setError(VBOX_E_NOT_SUPPORTED,
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync tr("Hard disk '%s' is not differencing"),
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync m->strLocationFull.raw());
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync if (m->autoReset != !!aAutoReset)
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync {
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync m->autoReset = !!aAutoReset;
eeebcc1f7aedfdbcaf7c4dae90ad932d5d9c03c8vboxsync
eeebcc1f7aedfdbcaf7c4dae90ad932d5d9c03c8vboxsync mlock.release();
eeebcc1f7aedfdbcaf7c4dae90ad932d5d9c03c8vboxsync
eeebcc1f7aedfdbcaf7c4dae90ad932d5d9c03c8vboxsync // saveSettings needs vbox lock
eeebcc1f7aedfdbcaf7c4dae90ad932d5d9c03c8vboxsync AutoWriteLock alock(m->pVirtualBox COMMA_LOCKVAL_SRC_POS);
eeebcc1f7aedfdbcaf7c4dae90ad932d5d9c03c8vboxsync
eeebcc1f7aedfdbcaf7c4dae90ad932d5d9c03c8vboxsync return m->pVirtualBox->saveSettings();
eeebcc1f7aedfdbcaf7c4dae90ad932d5d9c03c8vboxsync }
eeebcc1f7aedfdbcaf7c4dae90ad932d5d9c03c8vboxsync
eeebcc1f7aedfdbcaf7c4dae90ad932d5d9c03c8vboxsync return S_OK;
eeebcc1f7aedfdbcaf7c4dae90ad932d5d9c03c8vboxsync}
eeebcc1f7aedfdbcaf7c4dae90ad932d5d9c03c8vboxsyncSTDMETHODIMP Medium::COMGETTER(LastAccessError)(BSTR *aLastAccessError)
eeebcc1f7aedfdbcaf7c4dae90ad932d5d9c03c8vboxsync{
eeebcc1f7aedfdbcaf7c4dae90ad932d5d9c03c8vboxsync CheckComArgOutPointerValid(aLastAccessError);
eeebcc1f7aedfdbcaf7c4dae90ad932d5d9c03c8vboxsync
eeebcc1f7aedfdbcaf7c4dae90ad932d5d9c03c8vboxsync AutoCaller autoCaller(this);
eeebcc1f7aedfdbcaf7c4dae90ad932d5d9c03c8vboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
eeebcc1f7aedfdbcaf7c4dae90ad932d5d9c03c8vboxsync
eeebcc1f7aedfdbcaf7c4dae90ad932d5d9c03c8vboxsync AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
eeebcc1f7aedfdbcaf7c4dae90ad932d5d9c03c8vboxsync
eeebcc1f7aedfdbcaf7c4dae90ad932d5d9c03c8vboxsync m->strLastAccessError.cloneTo(aLastAccessError);
eeebcc1f7aedfdbcaf7c4dae90ad932d5d9c03c8vboxsync
cc15c3fa4bb2d3fb91e4d0cd15a73133963f86b0vboxsync return S_OK;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync}
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncSTDMETHODIMP Medium::COMGETTER(MachineIds)(ComSafeArrayOut(BSTR,aMachineIds))
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync{
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync CheckComArgOutSafeArrayPointerValid(aMachineIds);
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync AutoCaller autoCaller(this);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync com::SafeArray<BSTR> machineIds;
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync
eeebcc1f7aedfdbcaf7c4dae90ad932d5d9c03c8vboxsync if (m->backRefs.size() != 0)
eeebcc1f7aedfdbcaf7c4dae90ad932d5d9c03c8vboxsync {
eeebcc1f7aedfdbcaf7c4dae90ad932d5d9c03c8vboxsync machineIds.reset(m->backRefs.size());
1741b757f7a570a7e6d48db46c3f4cd50f2ee296vboxsync
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync size_t i = 0;
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync for (BackRefList::const_iterator it = m->backRefs.begin();
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync it != m->backRefs.end(); ++it, ++i)
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync {
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync it->machineId.toUtf16().detachTo(&machineIds[i]);
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync }
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync }
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync machineIds.detachTo(ComSafeArrayOutArg(aMachineIds));
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync return S_OK;
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync}
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsyncSTDMETHODIMP Medium::RefreshState(MediumState_T *aState)
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync{
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync CheckComArgOutPointerValid(aState);
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync AutoCaller autoCaller(this);
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync /* queryInfo() locks this for writing. */
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync HRESULT rc = S_OK;
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync switch (m->state)
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync {
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync case MediumState_Created:
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync case MediumState_Inaccessible:
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync case MediumState_LockedRead:
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync {
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync rc = queryInfo();
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync break;
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync }
b7a5b3f9f9ecce32ddacf8404c625ce0451bbdc1vboxsync default:
a0a5ab4e085a7ee5b95bdfae04cec7de95792c3cvboxsync break;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync }
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync *aState = m->state;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync return rc;
1fdf058ef3f645ee13c9957807e401ac3c9bc65bvboxsync}
1fdf058ef3f645ee13c9957807e401ac3c9bc65bvboxsync
1fdf058ef3f645ee13c9957807e401ac3c9bc65bvboxsyncSTDMETHODIMP Medium::GetSnapshotIds(IN_BSTR aMachineId,
1fdf058ef3f645ee13c9957807e401ac3c9bc65bvboxsync ComSafeArrayOut(BSTR, aSnapshotIds))
1fdf058ef3f645ee13c9957807e401ac3c9bc65bvboxsync{
1fdf058ef3f645ee13c9957807e401ac3c9bc65bvboxsync CheckComArgExpr(aMachineId, Guid(aMachineId).isEmpty() == false);
1fdf058ef3f645ee13c9957807e401ac3c9bc65bvboxsync CheckComArgOutSafeArrayPointerValid(aSnapshotIds);
1fdf058ef3f645ee13c9957807e401ac3c9bc65bvboxsync
1fdf058ef3f645ee13c9957807e401ac3c9bc65bvboxsync AutoCaller autoCaller(this);
1fdf058ef3f645ee13c9957807e401ac3c9bc65bvboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
1fdf058ef3f645ee13c9957807e401ac3c9bc65bvboxsync
1fdf058ef3f645ee13c9957807e401ac3c9bc65bvboxsync AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
1fdf058ef3f645ee13c9957807e401ac3c9bc65bvboxsync
1fdf058ef3f645ee13c9957807e401ac3c9bc65bvboxsync com::SafeArray<BSTR> snapshotIds;
1fdf058ef3f645ee13c9957807e401ac3c9bc65bvboxsync
1fdf058ef3f645ee13c9957807e401ac3c9bc65bvboxsync Guid id(aMachineId);
1fdf058ef3f645ee13c9957807e401ac3c9bc65bvboxsync for (BackRefList::const_iterator it = m->backRefs.begin();
1fdf058ef3f645ee13c9957807e401ac3c9bc65bvboxsync it != m->backRefs.end(); ++it)
1fdf058ef3f645ee13c9957807e401ac3c9bc65bvboxsync {
1fdf058ef3f645ee13c9957807e401ac3c9bc65bvboxsync if (it->machineId == id)
1fdf058ef3f645ee13c9957807e401ac3c9bc65bvboxsync {
1fdf058ef3f645ee13c9957807e401ac3c9bc65bvboxsync size_t size = it->llSnapshotIds.size();
1fdf058ef3f645ee13c9957807e401ac3c9bc65bvboxsync
1fdf058ef3f645ee13c9957807e401ac3c9bc65bvboxsync /* if the medium is attached to the machine in the current state, we
1fdf058ef3f645ee13c9957807e401ac3c9bc65bvboxsync * return its ID as the first element of the array */
1fdf058ef3f645ee13c9957807e401ac3c9bc65bvboxsync if (it->fInCurState)
1fdf058ef3f645ee13c9957807e401ac3c9bc65bvboxsync ++size;
1fdf058ef3f645ee13c9957807e401ac3c9bc65bvboxsync
1fdf058ef3f645ee13c9957807e401ac3c9bc65bvboxsync if (size > 0)
1fdf058ef3f645ee13c9957807e401ac3c9bc65bvboxsync {
1fdf058ef3f645ee13c9957807e401ac3c9bc65bvboxsync snapshotIds.reset(size);
1fdf058ef3f645ee13c9957807e401ac3c9bc65bvboxsync
1fdf058ef3f645ee13c9957807e401ac3c9bc65bvboxsync size_t j = 0;
1fdf058ef3f645ee13c9957807e401ac3c9bc65bvboxsync if (it->fInCurState)
1fdf058ef3f645ee13c9957807e401ac3c9bc65bvboxsync it->machineId.toUtf16().detachTo(&snapshotIds[j++]);
1fdf058ef3f645ee13c9957807e401ac3c9bc65bvboxsync
1fdf058ef3f645ee13c9957807e401ac3c9bc65bvboxsync for (BackRef::GuidList::const_iterator jt = it->llSnapshotIds.begin();
1fdf058ef3f645ee13c9957807e401ac3c9bc65bvboxsync jt != it->llSnapshotIds.end();
1fdf058ef3f645ee13c9957807e401ac3c9bc65bvboxsync ++jt, ++j)
1fdf058ef3f645ee13c9957807e401ac3c9bc65bvboxsync {
1fdf058ef3f645ee13c9957807e401ac3c9bc65bvboxsync (*jt).toUtf16().detachTo(&snapshotIds[j]);
1fdf058ef3f645ee13c9957807e401ac3c9bc65bvboxsync }
1fdf058ef3f645ee13c9957807e401ac3c9bc65bvboxsync }
1fdf058ef3f645ee13c9957807e401ac3c9bc65bvboxsync
1fdf058ef3f645ee13c9957807e401ac3c9bc65bvboxsync break;
1fdf058ef3f645ee13c9957807e401ac3c9bc65bvboxsync }
1fdf058ef3f645ee13c9957807e401ac3c9bc65bvboxsync }
1fdf058ef3f645ee13c9957807e401ac3c9bc65bvboxsync
1fdf058ef3f645ee13c9957807e401ac3c9bc65bvboxsync snapshotIds.detachTo(ComSafeArrayOutArg(aSnapshotIds));
1fdf058ef3f645ee13c9957807e401ac3c9bc65bvboxsync
1fdf058ef3f645ee13c9957807e401ac3c9bc65bvboxsync return S_OK;
1fdf058ef3f645ee13c9957807e401ac3c9bc65bvboxsync}
1fdf058ef3f645ee13c9957807e401ac3c9bc65bvboxsync
1fdf058ef3f645ee13c9957807e401ac3c9bc65bvboxsync/**
1fdf058ef3f645ee13c9957807e401ac3c9bc65bvboxsync * @note @a aState may be NULL if the state value is not needed (only for
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * in-process calls).
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync */
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsyncSTDMETHODIMP Medium::LockRead(MediumState_T *aState)
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync{
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync AutoCaller autoCaller(this);
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync
a0a5ab4e085a7ee5b95bdfae04cec7de95792c3cvboxsync AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync /* Wait for a concurrently running queryInfo() to complete */
eeebcc1f7aedfdbcaf7c4dae90ad932d5d9c03c8vboxsync while (m->queryInfoRunning)
eeebcc1f7aedfdbcaf7c4dae90ad932d5d9c03c8vboxsync {
eeebcc1f7aedfdbcaf7c4dae90ad932d5d9c03c8vboxsync alock.leave();
1741b757f7a570a7e6d48db46c3f4cd50f2ee296vboxsync RTSemEventMultiWait(m->queryInfoSem, RT_INDEFINITE_WAIT);
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync alock.enter();
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync }
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync /* return the current state before */
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync if (aState)
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync *aState = m->state;
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync
eeebcc1f7aedfdbcaf7c4dae90ad932d5d9c03c8vboxsync HRESULT rc = S_OK;
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync switch (m->state)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync {
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync case MediumState_Created:
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync case MediumState_Inaccessible:
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync case MediumState_LockedRead:
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync {
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync ++m->readers;
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync ComAssertMsgBreak(m->readers != 0, ("Counter overflow"), rc = E_FAIL);
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* Remember pre-lock state */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync if (m->state != MediumState_LockedRead)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync m->preLockState = m->state;
16a9adc14900ca18e6909679a579f6833425e030vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync LogFlowThisFunc(("Okay - prev state=%d readers=%d\n", m->state, m->readers));
16a9adc14900ca18e6909679a579f6833425e030vboxsync m->state = MediumState_LockedRead;
16a9adc14900ca18e6909679a579f6833425e030vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync break;
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync }
16a9adc14900ca18e6909679a579f6833425e030vboxsync default:
16a9adc14900ca18e6909679a579f6833425e030vboxsync {
16a9adc14900ca18e6909679a579f6833425e030vboxsync LogFlowThisFunc(("Failing - state=%d\n", m->state));
16a9adc14900ca18e6909679a579f6833425e030vboxsync rc = setStateError();
16a9adc14900ca18e6909679a579f6833425e030vboxsync break;
16a9adc14900ca18e6909679a579f6833425e030vboxsync }
16a9adc14900ca18e6909679a579f6833425e030vboxsync }
16a9adc14900ca18e6909679a579f6833425e030vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync return rc;
16a9adc14900ca18e6909679a579f6833425e030vboxsync}
16a9adc14900ca18e6909679a579f6833425e030vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync/**
16a9adc14900ca18e6909679a579f6833425e030vboxsync * @note @a aState may be NULL if the state value is not needed (only for
16a9adc14900ca18e6909679a579f6833425e030vboxsync * in-process calls).
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync */
e4f367251aede667a6de69baa54ef9eb5f150871vboxsyncSTDMETHODIMP Medium::UnlockRead(MediumState_T *aState)
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync{
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync AutoCaller autoCaller(this);
16a9adc14900ca18e6909679a579f6833425e030vboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
16a9adc14900ca18e6909679a579f6833425e030vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
16a9adc14900ca18e6909679a579f6833425e030vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync HRESULT rc = S_OK;
16a9adc14900ca18e6909679a579f6833425e030vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync switch (m->state)
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync {
16a9adc14900ca18e6909679a579f6833425e030vboxsync case MediumState_LockedRead:
16a9adc14900ca18e6909679a579f6833425e030vboxsync {
16a9adc14900ca18e6909679a579f6833425e030vboxsync Assert(m->readers != 0);
1741b757f7a570a7e6d48db46c3f4cd50f2ee296vboxsync --m->readers;
eeebcc1f7aedfdbcaf7c4dae90ad932d5d9c03c8vboxsync
1741b757f7a570a7e6d48db46c3f4cd50f2ee296vboxsync /* Reset the state after the last reader */
1741b757f7a570a7e6d48db46c3f4cd50f2ee296vboxsync if (m->readers == 0)
1741b757f7a570a7e6d48db46c3f4cd50f2ee296vboxsync {
1741b757f7a570a7e6d48db46c3f4cd50f2ee296vboxsync m->state = m->preLockState;
1741b757f7a570a7e6d48db46c3f4cd50f2ee296vboxsync /* There are cases where we inject the deleting state into
203cad92999b4792bf61b4b65e1e2abfe08f5664vboxsync * a medium locked for reading. Make sure #unmarkForDeletion()
1741b757f7a570a7e6d48db46c3f4cd50f2ee296vboxsync * gets the right state afterwards. */
1741b757f7a570a7e6d48db46c3f4cd50f2ee296vboxsync if (m->preLockState == MediumState_Deleting)
1741b757f7a570a7e6d48db46c3f4cd50f2ee296vboxsync m->preLockState = MediumState_Created;
eeebcc1f7aedfdbcaf7c4dae90ad932d5d9c03c8vboxsync }
eeebcc1f7aedfdbcaf7c4dae90ad932d5d9c03c8vboxsync
c5abe3ea9c7ac6dec34f42af30612534bea951ffvboxsync LogFlowThisFunc(("new state=%d\n", m->state));
c5abe3ea9c7ac6dec34f42af30612534bea951ffvboxsync break;
c5abe3ea9c7ac6dec34f42af30612534bea951ffvboxsync }
c5abe3ea9c7ac6dec34f42af30612534bea951ffvboxsync default:
f4fd9b62ec1cb6bb79fc7432a2d1a4c5f7c63bfcvboxsync {
c5abe3ea9c7ac6dec34f42af30612534bea951ffvboxsync LogFlowThisFunc(("Failing - state=%d\n", m->state));
9909b034014551f20c4e82bcb5caf6d2ae3c115dvboxsync rc = setError(VBOX_E_INVALID_OBJECT_STATE,
9909b034014551f20c4e82bcb5caf6d2ae3c115dvboxsync tr("Medium '%s' is not locked for reading"),
c5abe3ea9c7ac6dec34f42af30612534bea951ffvboxsync m->strLocationFull.raw());
1741b757f7a570a7e6d48db46c3f4cd50f2ee296vboxsync break;
c5abe3ea9c7ac6dec34f42af30612534bea951ffvboxsync }
c5abe3ea9c7ac6dec34f42af30612534bea951ffvboxsync }
c5abe3ea9c7ac6dec34f42af30612534bea951ffvboxsync
c5abe3ea9c7ac6dec34f42af30612534bea951ffvboxsync /* return the current state after */
1741b757f7a570a7e6d48db46c3f4cd50f2ee296vboxsync if (aState)
c5abe3ea9c7ac6dec34f42af30612534bea951ffvboxsync *aState = m->state;
203cad92999b4792bf61b4b65e1e2abfe08f5664vboxsync
c5abe3ea9c7ac6dec34f42af30612534bea951ffvboxsync return rc;
9909b034014551f20c4e82bcb5caf6d2ae3c115dvboxsync}
c5abe3ea9c7ac6dec34f42af30612534bea951ffvboxsync
c5abe3ea9c7ac6dec34f42af30612534bea951ffvboxsync/**
c5abe3ea9c7ac6dec34f42af30612534bea951ffvboxsync * @note @a aState may be NULL if the state value is not needed (only for
1741b757f7a570a7e6d48db46c3f4cd50f2ee296vboxsync * in-process calls).
c5abe3ea9c7ac6dec34f42af30612534bea951ffvboxsync */
f4fd9b62ec1cb6bb79fc7432a2d1a4c5f7c63bfcvboxsyncSTDMETHODIMP Medium::LockWrite(MediumState_T *aState)
c5abe3ea9c7ac6dec34f42af30612534bea951ffvboxsync{
c5abe3ea9c7ac6dec34f42af30612534bea951ffvboxsync AutoCaller autoCaller(this);
c5abe3ea9c7ac6dec34f42af30612534bea951ffvboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
1741b757f7a570a7e6d48db46c3f4cd50f2ee296vboxsync
1741b757f7a570a7e6d48db46c3f4cd50f2ee296vboxsync AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1741b757f7a570a7e6d48db46c3f4cd50f2ee296vboxsync
1741b757f7a570a7e6d48db46c3f4cd50f2ee296vboxsync /* Wait for a concurrently running queryInfo() to complete */
1741b757f7a570a7e6d48db46c3f4cd50f2ee296vboxsync while (m->queryInfoRunning)
1741b757f7a570a7e6d48db46c3f4cd50f2ee296vboxsync {
1741b757f7a570a7e6d48db46c3f4cd50f2ee296vboxsync alock.leave();
1741b757f7a570a7e6d48db46c3f4cd50f2ee296vboxsync RTSemEventMultiWait(m->queryInfoSem, RT_INDEFINITE_WAIT);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync alock.enter();
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync }
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync /* return the current state before */
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync if (aState)
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync *aState = m->state;
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync HRESULT rc = S_OK;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync switch (m->state)
e18d16f31765f000e2a4a111a3df6d211cd825f1vboxsync {
e18d16f31765f000e2a4a111a3df6d211cd825f1vboxsync case MediumState_Created:
e18d16f31765f000e2a4a111a3df6d211cd825f1vboxsync case MediumState_Inaccessible:
e18d16f31765f000e2a4a111a3df6d211cd825f1vboxsync {
e18d16f31765f000e2a4a111a3df6d211cd825f1vboxsync m->preLockState = m->state;
99afce7a96e1262ce137aa1fd4d2a911ebd644b1vboxsync
e18d16f31765f000e2a4a111a3df6d211cd825f1vboxsync LogFlowThisFunc(("Okay - prev state=%d locationFull=%s\n", m->state, getLocationFull().c_str()));
e18d16f31765f000e2a4a111a3df6d211cd825f1vboxsync m->state = MediumState_LockedWrite;
e18d16f31765f000e2a4a111a3df6d211cd825f1vboxsync break;
e18d16f31765f000e2a4a111a3df6d211cd825f1vboxsync }
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync default:
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync {
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync LogFlowThisFunc(("Failing - state=%d locationFull=%s\n", m->state, getLocationFull().c_str()));
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync rc = setStateError();
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync break;
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync }
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync }
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync return rc;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync}
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync/**
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync * @note @a aState may be NULL if the state value is not needed (only for
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * in-process calls).
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync */
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsyncSTDMETHODIMP Medium::UnlockWrite(MediumState_T *aState)
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync{
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync AutoCaller autoCaller(this);
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync HRESULT rc = S_OK;
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync switch (m->state)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync {
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync case MediumState_LockedWrite:
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync {
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync m->state = m->preLockState;
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync /* There are cases where we inject the deleting state into
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync * a medium locked for writing. Make sure #unmarkForDeletion()
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * gets the right state afterwards. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync if (m->preLockState == MediumState_Deleting)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync m->preLockState = MediumState_Created;
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync LogFlowThisFunc(("new state=%d locationFull=%s\n", m->state, getLocationFull().c_str()));
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync break;
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync }
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync default:
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync {
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync LogFlowThisFunc(("Failing - state=%d locationFull=%s\n", m->state, getLocationFull().c_str()));
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync rc = setError(VBOX_E_INVALID_OBJECT_STATE,
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync tr("Medium '%s' is not locked for writing"),
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync m->strLocationFull.raw());
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync break;
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync }
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync }
594521f7faf13f7a88f31e6cd76629bd67340229vboxsync
e04eeee1b306d610b0441cee9bf1c750100254d5vboxsync /* return the current state after */
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync if (aState)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync *aState = m->state;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync return rc;
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync}
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsyncSTDMETHODIMP Medium::Close()
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync{
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync AutoCaller autoCaller(this);
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync // we're accessing parent/child and backrefs, so lock the tree first, then ourselves
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync AutoMultiWriteLock2 multilock(&m->pVirtualBox->getMediaTreeLockHandle(),
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync this->lockHandle()
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync COMMA_LOCKVAL_SRC_POS);
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync bool wasCreated = true;
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync bool fNeedsSaveSettings = false;
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync switch (m->state)
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync {
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync case MediumState_NotCreated:
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync wasCreated = false;
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync break;
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync case MediumState_Created:
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync case MediumState_Inaccessible:
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync break;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync default:
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync return setStateError();
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync }
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync if (m->backRefs.size() != 0)
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync return setError(VBOX_E_OBJECT_IN_USE,
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync tr("Medium '%s' is attached to %d virtual machines"),
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync m->strLocationFull.raw(), m->backRefs.size());
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync /* perform extra media-dependent close checks */
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync HRESULT rc = canClose();
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync if (FAILED(rc)) return rc;
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync
594521f7faf13f7a88f31e6cd76629bd67340229vboxsync if (wasCreated)
e04eeee1b306d610b0441cee9bf1c750100254d5vboxsync {
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync /* remove from the list of known media before performing actual
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * uninitialization (to keep the media registry consistent on
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * failure to do so) */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync rc = unregisterWithVirtualBox(&fNeedsSaveSettings);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync if (FAILED(rc)) return rc;
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync }
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync // make a copy of VirtualBox pointer which gets nulled by uninit()
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync ComObjPtr<VirtualBox> pVirtualBox(m->pVirtualBox);
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync // leave the AutoCaller, as otherwise uninit() will simply hang
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync autoCaller.release();
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* Keep the locks held until after uninit, as otherwise the consistency
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync * of the medium tree cannot be guaranteed. */
e2ebb3d022edb845fd1158d6338e3def1d0e2159vboxsync uninit();
e2ebb3d022edb845fd1158d6338e3def1d0e2159vboxsync
e2ebb3d022edb845fd1158d6338e3def1d0e2159vboxsync multilock.release();
e2ebb3d022edb845fd1158d6338e3def1d0e2159vboxsync
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync if (fNeedsSaveSettings)
e2ebb3d022edb845fd1158d6338e3def1d0e2159vboxsync {
e2ebb3d022edb845fd1158d6338e3def1d0e2159vboxsync AutoWriteLock vboxlock(pVirtualBox COMMA_LOCKVAL_SRC_POS);
e2ebb3d022edb845fd1158d6338e3def1d0e2159vboxsync pVirtualBox->saveSettings();
e2ebb3d022edb845fd1158d6338e3def1d0e2159vboxsync }
47579c4cc64e7dff9b4de48841a2c4df3b96ab38vboxsync
47579c4cc64e7dff9b4de48841a2c4df3b96ab38vboxsync return S_OK;
47579c4cc64e7dff9b4de48841a2c4df3b96ab38vboxsync}
47579c4cc64e7dff9b4de48841a2c4df3b96ab38vboxsync
1bf320fa7c84120347a65cdbbf4d673f50abdbaevboxsyncSTDMETHODIMP Medium::GetProperty(IN_BSTR aName, BSTR *aValue)
47579c4cc64e7dff9b4de48841a2c4df3b96ab38vboxsync{
47579c4cc64e7dff9b4de48841a2c4df3b96ab38vboxsync CheckComArgStrNotEmptyOrNull(aName);
47579c4cc64e7dff9b4de48841a2c4df3b96ab38vboxsync CheckComArgOutPointerValid(aValue);
47579c4cc64e7dff9b4de48841a2c4df3b96ab38vboxsync
1bf320fa7c84120347a65cdbbf4d673f50abdbaevboxsync AutoCaller autoCaller(this);
47579c4cc64e7dff9b4de48841a2c4df3b96ab38vboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
47579c4cc64e7dff9b4de48841a2c4df3b96ab38vboxsync
47579c4cc64e7dff9b4de48841a2c4df3b96ab38vboxsync AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
1bf320fa7c84120347a65cdbbf4d673f50abdbaevboxsync
60a713666695ab3f2f6a0e43288c38e72f697d41vboxsync Data::PropertyMap::const_iterator it = m->properties.find(Bstr(aName));
1bf320fa7c84120347a65cdbbf4d673f50abdbaevboxsync if (it == m->properties.end())
60a713666695ab3f2f6a0e43288c38e72f697d41vboxsync return setError(VBOX_E_OBJECT_NOT_FOUND,
1bf320fa7c84120347a65cdbbf4d673f50abdbaevboxsync tr("Property '%ls' does not exist"), aName);
1bf320fa7c84120347a65cdbbf4d673f50abdbaevboxsync
60a713666695ab3f2f6a0e43288c38e72f697d41vboxsync it->second.cloneTo(aValue);
60a713666695ab3f2f6a0e43288c38e72f697d41vboxsync
47579c4cc64e7dff9b4de48841a2c4df3b96ab38vboxsync return S_OK;
47579c4cc64e7dff9b4de48841a2c4df3b96ab38vboxsync}
47579c4cc64e7dff9b4de48841a2c4df3b96ab38vboxsync
47579c4cc64e7dff9b4de48841a2c4df3b96ab38vboxsyncSTDMETHODIMP Medium::SetProperty(IN_BSTR aName, IN_BSTR aValue)
47579c4cc64e7dff9b4de48841a2c4df3b96ab38vboxsync{
47579c4cc64e7dff9b4de48841a2c4df3b96ab38vboxsync CheckComArgStrNotEmptyOrNull(aName);
47579c4cc64e7dff9b4de48841a2c4df3b96ab38vboxsync
47579c4cc64e7dff9b4de48841a2c4df3b96ab38vboxsync AutoCaller autoCaller(this);
47579c4cc64e7dff9b4de48841a2c4df3b96ab38vboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
47579c4cc64e7dff9b4de48841a2c4df3b96ab38vboxsync
47579c4cc64e7dff9b4de48841a2c4df3b96ab38vboxsync AutoWriteLock mlock(this COMMA_LOCKVAL_SRC_POS);
47579c4cc64e7dff9b4de48841a2c4df3b96ab38vboxsync
47579c4cc64e7dff9b4de48841a2c4df3b96ab38vboxsync switch (m->state)
47579c4cc64e7dff9b4de48841a2c4df3b96ab38vboxsync {
47579c4cc64e7dff9b4de48841a2c4df3b96ab38vboxsync case MediumState_Created:
47579c4cc64e7dff9b4de48841a2c4df3b96ab38vboxsync case MediumState_Inaccessible:
47579c4cc64e7dff9b4de48841a2c4df3b96ab38vboxsync break;
47579c4cc64e7dff9b4de48841a2c4df3b96ab38vboxsync default:
47579c4cc64e7dff9b4de48841a2c4df3b96ab38vboxsync return setStateError();
47579c4cc64e7dff9b4de48841a2c4df3b96ab38vboxsync }
47579c4cc64e7dff9b4de48841a2c4df3b96ab38vboxsync
47579c4cc64e7dff9b4de48841a2c4df3b96ab38vboxsync Data::PropertyMap::iterator it = m->properties.find(Bstr(aName));
47579c4cc64e7dff9b4de48841a2c4df3b96ab38vboxsync if (it == m->properties.end())
47579c4cc64e7dff9b4de48841a2c4df3b96ab38vboxsync return setError(VBOX_E_OBJECT_NOT_FOUND,
47579c4cc64e7dff9b4de48841a2c4df3b96ab38vboxsync tr("Property '%ls' does not exist"),
47579c4cc64e7dff9b4de48841a2c4df3b96ab38vboxsync aName);
9496f2d398b49813176939d7a339ae513d5175efvboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsync if (aValue && !*aValue)
9496f2d398b49813176939d7a339ae513d5175efvboxsync it->second = (const char *)NULL;
9496f2d398b49813176939d7a339ae513d5175efvboxsync else
f687f34bd232be13744edbc0cc5155fa5d4540edvboxsync it->second = aValue;
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync
7a3f491705173bc08122f2c7d26d48a8b4c5ceecvboxsync mlock.release();
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync
009d45aa55691312278d41edb20154dc208d9cd8vboxsync // saveSettings needs vbox lock
009d45aa55691312278d41edb20154dc208d9cd8vboxsync AutoWriteLock alock(m->pVirtualBox COMMA_LOCKVAL_SRC_POS);
009d45aa55691312278d41edb20154dc208d9cd8vboxsync HRESULT rc = m->pVirtualBox->saveSettings();
009d45aa55691312278d41edb20154dc208d9cd8vboxsync
009d45aa55691312278d41edb20154dc208d9cd8vboxsync return rc;
009d45aa55691312278d41edb20154dc208d9cd8vboxsync}
009d45aa55691312278d41edb20154dc208d9cd8vboxsync
009d45aa55691312278d41edb20154dc208d9cd8vboxsyncSTDMETHODIMP Medium::GetProperties(IN_BSTR aNames,
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync ComSafeArrayOut(BSTR, aReturnNames),
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync ComSafeArrayOut(BSTR, aReturnValues))
b7a5b3f9f9ecce32ddacf8404c625ce0451bbdc1vboxsync{
a9f41cb889f53e8407561a6155052c441eb0fc5fvboxsync CheckComArgOutSafeArrayPointerValid(aReturnNames);
9496f2d398b49813176939d7a339ae513d5175efvboxsync CheckComArgOutSafeArrayPointerValid(aReturnValues);
9496f2d398b49813176939d7a339ae513d5175efvboxsync
009d45aa55691312278d41edb20154dc208d9cd8vboxsync AutoCaller autoCaller(this);
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
009d45aa55691312278d41edb20154dc208d9cd8vboxsync
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync
eeebcc1f7aedfdbcaf7c4dae90ad932d5d9c03c8vboxsync /// @todo make use of aNames according to the documentation
eeebcc1f7aedfdbcaf7c4dae90ad932d5d9c03c8vboxsync NOREF(aNames);
eeebcc1f7aedfdbcaf7c4dae90ad932d5d9c03c8vboxsync
1741b757f7a570a7e6d48db46c3f4cd50f2ee296vboxsync com::SafeArray<BSTR> names(m->properties.size());
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync com::SafeArray<BSTR> values(m->properties.size());
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync size_t i = 0;
19badc2a6bdaeb1208f71b7de06feec1aa7c59c9vboxsync
19badc2a6bdaeb1208f71b7de06feec1aa7c59c9vboxsync for (Data::PropertyMap::const_iterator it = m->properties.begin();
009d45aa55691312278d41edb20154dc208d9cd8vboxsync it != m->properties.end();
009d45aa55691312278d41edb20154dc208d9cd8vboxsync ++it)
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync {
009d45aa55691312278d41edb20154dc208d9cd8vboxsync it->first.cloneTo(&names[i]);
009d45aa55691312278d41edb20154dc208d9cd8vboxsync it->second.cloneTo(&values[i]);
009d45aa55691312278d41edb20154dc208d9cd8vboxsync ++i;
009d45aa55691312278d41edb20154dc208d9cd8vboxsync }
009d45aa55691312278d41edb20154dc208d9cd8vboxsync
009d45aa55691312278d41edb20154dc208d9cd8vboxsync names.detachTo(ComSafeArrayOutArg(aReturnNames));
009d45aa55691312278d41edb20154dc208d9cd8vboxsync values.detachTo(ComSafeArrayOutArg(aReturnValues));
009d45aa55691312278d41edb20154dc208d9cd8vboxsync
009d45aa55691312278d41edb20154dc208d9cd8vboxsync return S_OK;
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync}
9496f2d398b49813176939d7a339ae513d5175efvboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsyncSTDMETHODIMP Medium::SetProperties(ComSafeArrayIn(IN_BSTR, aNames),
9496f2d398b49813176939d7a339ae513d5175efvboxsync ComSafeArrayIn(IN_BSTR, aValues))
9496f2d398b49813176939d7a339ae513d5175efvboxsync{
a9f41cb889f53e8407561a6155052c441eb0fc5fvboxsync CheckComArgSafeArrayNotNull(aNames);
9496f2d398b49813176939d7a339ae513d5175efvboxsync CheckComArgSafeArrayNotNull(aValues);
9496f2d398b49813176939d7a339ae513d5175efvboxsync
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync AutoCaller autoCaller(this);
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
009d45aa55691312278d41edb20154dc208d9cd8vboxsync
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync AutoWriteLock mlock(this COMMA_LOCKVAL_SRC_POS);
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync
eeebcc1f7aedfdbcaf7c4dae90ad932d5d9c03c8vboxsync com::SafeArray<IN_BSTR> names(ComSafeArrayInArg(aNames));
eeebcc1f7aedfdbcaf7c4dae90ad932d5d9c03c8vboxsync com::SafeArray<IN_BSTR> values(ComSafeArrayInArg(aValues));
eeebcc1f7aedfdbcaf7c4dae90ad932d5d9c03c8vboxsync
1741b757f7a570a7e6d48db46c3f4cd50f2ee296vboxsync /* first pass: validate names */
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync for (size_t i = 0;
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync i < names.size();
19badc2a6bdaeb1208f71b7de06feec1aa7c59c9vboxsync ++i)
19badc2a6bdaeb1208f71b7de06feec1aa7c59c9vboxsync {
009d45aa55691312278d41edb20154dc208d9cd8vboxsync if (m->properties.find(Bstr(names[i])) == m->properties.end())
009d45aa55691312278d41edb20154dc208d9cd8vboxsync return setError(VBOX_E_OBJECT_NOT_FOUND,
009d45aa55691312278d41edb20154dc208d9cd8vboxsync tr("Property '%ls' does not exist"), names[i]);
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync }
009d45aa55691312278d41edb20154dc208d9cd8vboxsync
009d45aa55691312278d41edb20154dc208d9cd8vboxsync /* second pass: assign */
009d45aa55691312278d41edb20154dc208d9cd8vboxsync for (size_t i = 0;
009d45aa55691312278d41edb20154dc208d9cd8vboxsync i < names.size();
009d45aa55691312278d41edb20154dc208d9cd8vboxsync ++i)
009d45aa55691312278d41edb20154dc208d9cd8vboxsync {
009d45aa55691312278d41edb20154dc208d9cd8vboxsync Data::PropertyMap::iterator it = m->properties.find(Bstr(names[i]));
009d45aa55691312278d41edb20154dc208d9cd8vboxsync AssertReturn(it != m->properties.end(), E_FAIL);
009d45aa55691312278d41edb20154dc208d9cd8vboxsync
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync if (values[i] && !*values[i])
9496f2d398b49813176939d7a339ae513d5175efvboxsync it->second = (const char *)NULL;
9496f2d398b49813176939d7a339ae513d5175efvboxsync else
9496f2d398b49813176939d7a339ae513d5175efvboxsync it->second = values[i];
fc78e01f665145ab3641c5f8095e9ae984ddcb84vboxsync }
fc78e01f665145ab3641c5f8095e9ae984ddcb84vboxsync
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync mlock.release();
009d45aa55691312278d41edb20154dc208d9cd8vboxsync
fc78e01f665145ab3641c5f8095e9ae984ddcb84vboxsync // saveSettings needs vbox lock
009d45aa55691312278d41edb20154dc208d9cd8vboxsync AutoWriteLock alock(m->pVirtualBox COMMA_LOCKVAL_SRC_POS);
009d45aa55691312278d41edb20154dc208d9cd8vboxsync HRESULT rc = m->pVirtualBox->saveSettings();
009d45aa55691312278d41edb20154dc208d9cd8vboxsync
009d45aa55691312278d41edb20154dc208d9cd8vboxsync return rc;
009d45aa55691312278d41edb20154dc208d9cd8vboxsync}
009d45aa55691312278d41edb20154dc208d9cd8vboxsync
bdaae7f756db4f5cf2d62f495a2a80acaf581a0cvboxsyncSTDMETHODIMP Medium::CreateBaseStorage(ULONG64 aLogicalSize,
bdaae7f756db4f5cf2d62f495a2a80acaf581a0cvboxsync MediumVariant_T aVariant,
bdaae7f756db4f5cf2d62f495a2a80acaf581a0cvboxsync IProgress **aProgress)
bdaae7f756db4f5cf2d62f495a2a80acaf581a0cvboxsync{
009d45aa55691312278d41edb20154dc208d9cd8vboxsync CheckComArgOutPointerValid(aProgress);
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync
fc78e01f665145ab3641c5f8095e9ae984ddcb84vboxsync AutoCaller autoCaller(this);
fc78e01f665145ab3641c5f8095e9ae984ddcb84vboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
fc78e01f665145ab3641c5f8095e9ae984ddcb84vboxsync
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync HRESULT rc = S_OK;
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync ComObjPtr <Progress> pProgress;
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync Medium::Task *pTask = NULL;
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync try
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync {
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync aVariant = (MediumVariant_T)((unsigned)aVariant & (unsigned)~MediumVariant_Diff);
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync if ( !(aVariant & MediumVariant_Fixed)
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync && !(m->formatObj->capabilities() & MediumFormatCapabilities_CreateDynamic))
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync throw setError(VBOX_E_NOT_SUPPORTED,
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync tr("Hard disk format '%s' does not support dynamic storage creation"),
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync m->strFormat.raw());
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync if ( (aVariant & MediumVariant_Fixed)
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync && !(m->formatObj->capabilities() & MediumFormatCapabilities_CreateDynamic))
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync throw setError(VBOX_E_NOT_SUPPORTED,
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync tr("Hard disk format '%s' does not support fixed storage creation"),
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync m->strFormat.raw());
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync if (m->state != MediumState_NotCreated)
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync throw setStateError();
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync pProgress.createObject();
009d45aa55691312278d41edb20154dc208d9cd8vboxsync rc = pProgress->init(m->pVirtualBox,
009d45aa55691312278d41edb20154dc208d9cd8vboxsync static_cast<IMedium*>(this),
009d45aa55691312278d41edb20154dc208d9cd8vboxsync (aVariant & MediumVariant_Fixed)
009d45aa55691312278d41edb20154dc208d9cd8vboxsync ? BstrFmt(tr("Creating fixed hard disk storage unit '%s'"), m->strLocationFull.raw())
009d45aa55691312278d41edb20154dc208d9cd8vboxsync : BstrFmt(tr("Creating dynamic hard disk storage unit '%s'"), m->strLocationFull.raw()),
009d45aa55691312278d41edb20154dc208d9cd8vboxsync TRUE /* aCancelable */);
009d45aa55691312278d41edb20154dc208d9cd8vboxsync if (FAILED(rc))
009d45aa55691312278d41edb20154dc208d9cd8vboxsync throw rc;
009d45aa55691312278d41edb20154dc208d9cd8vboxsync
009d45aa55691312278d41edb20154dc208d9cd8vboxsync /* setup task object to carry out the operation asynchronously */
009d45aa55691312278d41edb20154dc208d9cd8vboxsync pTask = new Medium::CreateBaseTask(this, pProgress, aLogicalSize,
009d45aa55691312278d41edb20154dc208d9cd8vboxsync aVariant);
009d45aa55691312278d41edb20154dc208d9cd8vboxsync rc = pTask->rc();
009d45aa55691312278d41edb20154dc208d9cd8vboxsync AssertComRC(rc);
009d45aa55691312278d41edb20154dc208d9cd8vboxsync if (FAILED(rc))
009d45aa55691312278d41edb20154dc208d9cd8vboxsync throw rc;
009d45aa55691312278d41edb20154dc208d9cd8vboxsync
009d45aa55691312278d41edb20154dc208d9cd8vboxsync m->state = MediumState_Creating;
009d45aa55691312278d41edb20154dc208d9cd8vboxsync }
203cad92999b4792bf61b4b65e1e2abfe08f5664vboxsync catch (HRESULT aRC) { rc = aRC; }
1741b757f7a570a7e6d48db46c3f4cd50f2ee296vboxsync
009d45aa55691312278d41edb20154dc208d9cd8vboxsync if (SUCCEEDED(rc))
009d45aa55691312278d41edb20154dc208d9cd8vboxsync {
009d45aa55691312278d41edb20154dc208d9cd8vboxsync rc = startThread(pTask);
009d45aa55691312278d41edb20154dc208d9cd8vboxsync
009d45aa55691312278d41edb20154dc208d9cd8vboxsync if (SUCCEEDED(rc))
009d45aa55691312278d41edb20154dc208d9cd8vboxsync pProgress.queryInterfaceTo(aProgress);
009d45aa55691312278d41edb20154dc208d9cd8vboxsync }
009d45aa55691312278d41edb20154dc208d9cd8vboxsync else if (pTask != NULL)
009d45aa55691312278d41edb20154dc208d9cd8vboxsync delete pTask;
009d45aa55691312278d41edb20154dc208d9cd8vboxsync
009d45aa55691312278d41edb20154dc208d9cd8vboxsync return rc;
009d45aa55691312278d41edb20154dc208d9cd8vboxsync}
009d45aa55691312278d41edb20154dc208d9cd8vboxsync
009d45aa55691312278d41edb20154dc208d9cd8vboxsyncSTDMETHODIMP Medium::DeleteStorage(IProgress **aProgress)
009d45aa55691312278d41edb20154dc208d9cd8vboxsync{
009d45aa55691312278d41edb20154dc208d9cd8vboxsync CheckComArgOutPointerValid(aProgress);
009d45aa55691312278d41edb20154dc208d9cd8vboxsync
009d45aa55691312278d41edb20154dc208d9cd8vboxsync AutoCaller autoCaller(this);
009d45aa55691312278d41edb20154dc208d9cd8vboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
009d45aa55691312278d41edb20154dc208d9cd8vboxsync
009d45aa55691312278d41edb20154dc208d9cd8vboxsync bool fNeedsSaveSettings = false;
009d45aa55691312278d41edb20154dc208d9cd8vboxsync ComObjPtr <Progress> pProgress;
009d45aa55691312278d41edb20154dc208d9cd8vboxsync
009d45aa55691312278d41edb20154dc208d9cd8vboxsync HRESULT rc = deleteStorage(&pProgress,
009d45aa55691312278d41edb20154dc208d9cd8vboxsync false /* aWait */,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync &fNeedsSaveSettings);
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync if (fNeedsSaveSettings)
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync {
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync AutoWriteLock vboxlock(m->pVirtualBox COMMA_LOCKVAL_SRC_POS);
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync m->pVirtualBox->saveSettings();
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync }
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync if (SUCCEEDED(rc))
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync pProgress.queryInterfaceTo(aProgress);
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync return rc;
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync}
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsyncSTDMETHODIMP Medium::CreateDiffStorage(IMedium *aTarget,
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync MediumVariant_T aVariant,
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync IProgress **aProgress)
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync{
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync CheckComArgNotNull(aTarget);
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync CheckComArgOutPointerValid(aProgress);
10e818af327731667e40ed25ee3e70ab5ea2cc4cvboxsync
10e818af327731667e40ed25ee3e70ab5ea2cc4cvboxsync AutoCaller autoCaller(this);
10e818af327731667e40ed25ee3e70ab5ea2cc4cvboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
10e818af327731667e40ed25ee3e70ab5ea2cc4cvboxsync
10e818af327731667e40ed25ee3e70ab5ea2cc4cvboxsync ComObjPtr<Medium> diff = static_cast<Medium*>(aTarget);
10e818af327731667e40ed25ee3e70ab5ea2cc4cvboxsync
10e818af327731667e40ed25ee3e70ab5ea2cc4cvboxsync AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
10e818af327731667e40ed25ee3e70ab5ea2cc4cvboxsync
10e818af327731667e40ed25ee3e70ab5ea2cc4cvboxsync if (m->type == MediumType_Writethrough)
10e818af327731667e40ed25ee3e70ab5ea2cc4cvboxsync return setError(E_FAIL,
10e818af327731667e40ed25ee3e70ab5ea2cc4cvboxsync tr("Hard disk '%s' is Writethrough"),
10e818af327731667e40ed25ee3e70ab5ea2cc4cvboxsync m->strLocationFull.raw());
10e818af327731667e40ed25ee3e70ab5ea2cc4cvboxsync
10e818af327731667e40ed25ee3e70ab5ea2cc4cvboxsync /* Apply the normal locking logic to the entire chain. */
10e818af327731667e40ed25ee3e70ab5ea2cc4cvboxsync MediumLockList *pMediumLockList(new MediumLockList());
10e818af327731667e40ed25ee3e70ab5ea2cc4cvboxsync HRESULT rc = diff->createMediumLockList(true /* fFailIfInaccessible */,
10e818af327731667e40ed25ee3e70ab5ea2cc4cvboxsync true /* fMediumLockWrite */,
10e818af327731667e40ed25ee3e70ab5ea2cc4cvboxsync this,
10e818af327731667e40ed25ee3e70ab5ea2cc4cvboxsync *pMediumLockList);
10e818af327731667e40ed25ee3e70ab5ea2cc4cvboxsync if (FAILED(rc))
10e818af327731667e40ed25ee3e70ab5ea2cc4cvboxsync {
10e818af327731667e40ed25ee3e70ab5ea2cc4cvboxsync delete pMediumLockList;
10e818af327731667e40ed25ee3e70ab5ea2cc4cvboxsync return rc;
10e818af327731667e40ed25ee3e70ab5ea2cc4cvboxsync }
10e818af327731667e40ed25ee3e70ab5ea2cc4cvboxsync
10e818af327731667e40ed25ee3e70ab5ea2cc4cvboxsync ComObjPtr <Progress> pProgress;
10e818af327731667e40ed25ee3e70ab5ea2cc4cvboxsync
10e818af327731667e40ed25ee3e70ab5ea2cc4cvboxsync rc = createDiffStorage(diff, aVariant, pMediumLockList, &pProgress,
10e818af327731667e40ed25ee3e70ab5ea2cc4cvboxsync false /* aWait */, NULL /* pfNeedsSaveSettings*/);
10e818af327731667e40ed25ee3e70ab5ea2cc4cvboxsync if (FAILED(rc))
10e818af327731667e40ed25ee3e70ab5ea2cc4cvboxsync delete pMediumLockList;
baacecc94a2d23b6f5086739c08cf06d6b357d0avboxsync else
baacecc94a2d23b6f5086739c08cf06d6b357d0avboxsync pProgress.queryInterfaceTo(aProgress);
baacecc94a2d23b6f5086739c08cf06d6b357d0avboxsync
baacecc94a2d23b6f5086739c08cf06d6b357d0avboxsync return rc;
baacecc94a2d23b6f5086739c08cf06d6b357d0avboxsync}
baacecc94a2d23b6f5086739c08cf06d6b357d0avboxsync
baacecc94a2d23b6f5086739c08cf06d6b357d0avboxsyncSTDMETHODIMP Medium::MergeTo(IMedium *aTarget, IProgress **aProgress)
baacecc94a2d23b6f5086739c08cf06d6b357d0avboxsync{
baacecc94a2d23b6f5086739c08cf06d6b357d0avboxsync CheckComArgNotNull(aTarget);
baacecc94a2d23b6f5086739c08cf06d6b357d0avboxsync CheckComArgOutPointerValid(aProgress);
baacecc94a2d23b6f5086739c08cf06d6b357d0avboxsync ComAssertRet(aTarget != this, E_INVALIDARG);
baacecc94a2d23b6f5086739c08cf06d6b357d0avboxsync
baacecc94a2d23b6f5086739c08cf06d6b357d0avboxsync AutoCaller autoCaller(this);
baacecc94a2d23b6f5086739c08cf06d6b357d0avboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
baacecc94a2d23b6f5086739c08cf06d6b357d0avboxsync
baacecc94a2d23b6f5086739c08cf06d6b357d0avboxsync ComObjPtr<Medium> pTarget = static_cast<Medium*>(aTarget);
baacecc94a2d23b6f5086739c08cf06d6b357d0avboxsync
baacecc94a2d23b6f5086739c08cf06d6b357d0avboxsync bool fMergeForward = false;
baacecc94a2d23b6f5086739c08cf06d6b357d0avboxsync ComObjPtr<Medium> pParentForTarget;
baacecc94a2d23b6f5086739c08cf06d6b357d0avboxsync MediaList childrenToReparent;
baacecc94a2d23b6f5086739c08cf06d6b357d0avboxsync MediumLockList *pMediumLockList = NULL;
baacecc94a2d23b6f5086739c08cf06d6b357d0avboxsync
baacecc94a2d23b6f5086739c08cf06d6b357d0avboxsync HRESULT rc = S_OK;
baacecc94a2d23b6f5086739c08cf06d6b357d0avboxsync
baacecc94a2d23b6f5086739c08cf06d6b357d0avboxsync rc = prepareMergeTo(pTarget, NULL, NULL, true, fMergeForward,
baacecc94a2d23b6f5086739c08cf06d6b357d0avboxsync pParentForTarget, childrenToReparent, pMediumLockList);
baacecc94a2d23b6f5086739c08cf06d6b357d0avboxsync if (FAILED(rc)) return rc;
baacecc94a2d23b6f5086739c08cf06d6b357d0avboxsync
baacecc94a2d23b6f5086739c08cf06d6b357d0avboxsync ComObjPtr <Progress> pProgress;
baacecc94a2d23b6f5086739c08cf06d6b357d0avboxsync
f4fd9b62ec1cb6bb79fc7432a2d1a4c5f7c63bfcvboxsync rc = mergeTo(pTarget, fMergeForward, pParentForTarget, childrenToReparent,
baacecc94a2d23b6f5086739c08cf06d6b357d0avboxsync pMediumLockList, &pProgress, false /* aWait */,
baacecc94a2d23b6f5086739c08cf06d6b357d0avboxsync NULL /* pfNeedsSaveSettings */);
baacecc94a2d23b6f5086739c08cf06d6b357d0avboxsync if (FAILED(rc))
baacecc94a2d23b6f5086739c08cf06d6b357d0avboxsync cancelMergeTo(childrenToReparent, pMediumLockList);
baacecc94a2d23b6f5086739c08cf06d6b357d0avboxsync else
baacecc94a2d23b6f5086739c08cf06d6b357d0avboxsync pProgress.queryInterfaceTo(aProgress);
baacecc94a2d23b6f5086739c08cf06d6b357d0avboxsync
baacecc94a2d23b6f5086739c08cf06d6b357d0avboxsync return rc;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync}
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncSTDMETHODIMP Medium::CloneTo(IMedium *aTarget,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync MediumVariant_T aVariant,
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync IMedium *aParent,
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync IProgress **aProgress)
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync{
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync CheckComArgNotNull(aTarget);
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync CheckComArgOutPointerValid(aProgress);
9daee41d5cb5a2e8390f015a486e67a6cd52b836vboxsync ComAssertRet(aTarget != this, E_INVALIDARG);
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync AutoCaller autoCaller(this);
a39ea3668b7019c23a68936259545f9b71bce1aavboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
da3503c04ce76e653401396fe2795a9bc2427a1dvboxsync
da3503c04ce76e653401396fe2795a9bc2427a1dvboxsync ComObjPtr<Medium> pTarget = static_cast<Medium*>(aTarget);
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync ComObjPtr<Medium> pParent;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync if (aParent)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pParent = static_cast<Medium*>(aParent);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync HRESULT rc = S_OK;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync ComObjPtr<Progress> pProgress;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync Medium::Task *pTask = NULL;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync try
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync {
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync // locking: we need the tree lock first because we access parent pointers
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync AutoReadLock treeLock(m->pVirtualBox->getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS);
ad27e1d5e48ca41245120c331cc88b50464813cevboxsync // and we need to write-lock the images involved
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync AutoMultiWriteLock3 alock(this, pTarget, pParent COMMA_LOCKVAL_SRC_POS);
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync if ( pTarget->m->state != MediumState_NotCreated
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync && pTarget->m->state != MediumState_Created)
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync throw pTarget->setStateError();
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync /* Build the source lock list. */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync MediumLockList *pSourceMediumLockList(new MediumLockList());
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync rc = createMediumLockList(true /* fFailIfInaccessible */,
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync false /* fMediumLockWrite */,
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync NULL,
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync *pSourceMediumLockList);
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync if (FAILED(rc))
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync {
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync delete pSourceMediumLockList;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync throw rc;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync }
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync /* Build the target lock list (including the to-be parent chain). */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync MediumLockList *pTargetMediumLockList(new MediumLockList());
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync rc = pTarget->createMediumLockList(true /* fFailIfInaccessible */,
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync true /* fMediumLockWrite */,
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pParent,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync *pTargetMediumLockList);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync if (FAILED(rc))
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync {
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync delete pSourceMediumLockList;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync delete pTargetMediumLockList;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync throw rc;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync }
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync rc = pSourceMediumLockList->Lock();
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync if (FAILED(rc))
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync {
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync delete pSourceMediumLockList;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync delete pTargetMediumLockList;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync throw setError(rc,
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync tr("Failed to lock source media '%s'"),
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync getLocationFull().raw());
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync }
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync rc = pTargetMediumLockList->Lock();
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync if (FAILED(rc))
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync {
a5e6836247bf89fb87d0fdf08c1ac8c79dd979advboxsync delete pSourceMediumLockList;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync delete pTargetMediumLockList;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync throw setError(rc,
a5e6836247bf89fb87d0fdf08c1ac8c79dd979advboxsync tr("Failed to lock target media '%s'"),
a5e6836247bf89fb87d0fdf08c1ac8c79dd979advboxsync pTarget->getLocationFull().raw());
a5e6836247bf89fb87d0fdf08c1ac8c79dd979advboxsync }
a5e6836247bf89fb87d0fdf08c1ac8c79dd979advboxsync
a5e6836247bf89fb87d0fdf08c1ac8c79dd979advboxsync pProgress.createObject();
a5e6836247bf89fb87d0fdf08c1ac8c79dd979advboxsync rc = pProgress->init(m->pVirtualBox,
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync static_cast <IMedium *>(this),
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync BstrFmt(tr("Creating clone hard disk '%s'"), pTarget->m->strLocationFull.raw()),
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync TRUE /* aCancelable */);
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync if (FAILED(rc))
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync {
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync delete pSourceMediumLockList;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync delete pTargetMediumLockList;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync throw rc;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync }
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync /* setup task object to carry out the operation asynchronously */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pTask = new Medium::CloneTask(this, pProgress, pTarget, aVariant,
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pParent, pSourceMediumLockList,
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pTargetMediumLockList);
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync rc = pTask->rc();
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync AssertComRC(rc);
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync if (FAILED(rc))
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync throw rc;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync if (pTarget->m->state == MediumState_NotCreated)
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pTarget->m->state = MediumState_Creating;
a5e6836247bf89fb87d0fdf08c1ac8c79dd979advboxsync }
a5e6836247bf89fb87d0fdf08c1ac8c79dd979advboxsync catch (HRESULT aRC) { rc = aRC; }
a5e6836247bf89fb87d0fdf08c1ac8c79dd979advboxsync
a5e6836247bf89fb87d0fdf08c1ac8c79dd979advboxsync if (SUCCEEDED(rc))
a5e6836247bf89fb87d0fdf08c1ac8c79dd979advboxsync {
a5e6836247bf89fb87d0fdf08c1ac8c79dd979advboxsync rc = startThread(pTask);
a5e6836247bf89fb87d0fdf08c1ac8c79dd979advboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync if (SUCCEEDED(rc))
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pProgress.queryInterfaceTo(aProgress);
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync }
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync else if (pTask != NULL)
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync delete pTask;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync return rc;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync}
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsyncSTDMETHODIMP Medium::Compact(IProgress **aProgress)
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync{
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync CheckComArgOutPointerValid(aProgress);
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync AutoCaller autoCaller(this);
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync HRESULT rc = S_OK;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync ComObjPtr <Progress> pProgress;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync Medium::Task *pTask = NULL;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync try
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync {
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync /* We need to lock both the current object, and the tree lock (would
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync * cause a lock order violation otherwise) for createMediumLockList. */
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync AutoMultiWriteLock2 multilock(&m->pVirtualBox->getMediaTreeLockHandle(),
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync this->lockHandle()
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync COMMA_LOCKVAL_SRC_POS);
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync
ff5f52502d5dff6a8f353c85702ef49cc25c2f6bvboxsync /* Build the medium lock list. */
ff5f52502d5dff6a8f353c85702ef49cc25c2f6bvboxsync MediumLockList *pMediumLockList(new MediumLockList());
ff5f52502d5dff6a8f353c85702ef49cc25c2f6bvboxsync rc = createMediumLockList(true /* fFailIfInaccessible */ ,
ff5f52502d5dff6a8f353c85702ef49cc25c2f6bvboxsync true /* fMediumLockWrite */,
ff5f52502d5dff6a8f353c85702ef49cc25c2f6bvboxsync NULL,
ff5f52502d5dff6a8f353c85702ef49cc25c2f6bvboxsync *pMediumLockList);
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync if (FAILED(rc))
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync {
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync delete pMediumLockList;
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync throw rc;
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync }
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync rc = pMediumLockList->Lock();
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync if (FAILED(rc))
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync {
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync delete pMediumLockList;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync throw setError(rc,
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync tr("Failed to lock media when compacting '%s'"),
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync getLocationFull().raw());
1e1273b11e17928ec3c3a8fff45121aa7a169413vboxsync }
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync pProgress.createObject();
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync rc = pProgress->init(m->pVirtualBox,
c7ff622115966b69b482bd2896662e40d823b22fvboxsync static_cast <IMedium *>(this),
c7ff622115966b69b482bd2896662e40d823b22fvboxsync BstrFmt(tr("Compacting hard disk '%s'"), m->strLocationFull.raw()),
16a9adc14900ca18e6909679a579f6833425e030vboxsync TRUE /* aCancelable */);
16a9adc14900ca18e6909679a579f6833425e030vboxsync if (FAILED(rc))
16a9adc14900ca18e6909679a579f6833425e030vboxsync {
16a9adc14900ca18e6909679a579f6833425e030vboxsync delete pMediumLockList;
16a9adc14900ca18e6909679a579f6833425e030vboxsync throw rc;
16a9adc14900ca18e6909679a579f6833425e030vboxsync }
16a9adc14900ca18e6909679a579f6833425e030vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync /* setup task object to carry out the operation asynchronously */
16a9adc14900ca18e6909679a579f6833425e030vboxsync pTask = new Medium::CompactTask(this, pProgress, pMediumLockList);
16a9adc14900ca18e6909679a579f6833425e030vboxsync rc = pTask->rc();
16a9adc14900ca18e6909679a579f6833425e030vboxsync AssertComRC(rc);
16a9adc14900ca18e6909679a579f6833425e030vboxsync if (FAILED(rc))
16a9adc14900ca18e6909679a579f6833425e030vboxsync throw rc;
1e1273b11e17928ec3c3a8fff45121aa7a169413vboxsync }
009d45aa55691312278d41edb20154dc208d9cd8vboxsync catch (HRESULT aRC) { rc = aRC; }
009d45aa55691312278d41edb20154dc208d9cd8vboxsync
009d45aa55691312278d41edb20154dc208d9cd8vboxsync if (SUCCEEDED(rc))
009d45aa55691312278d41edb20154dc208d9cd8vboxsync {
009d45aa55691312278d41edb20154dc208d9cd8vboxsync rc = startThread(pTask);
1e1273b11e17928ec3c3a8fff45121aa7a169413vboxsync
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync if (SUCCEEDED(rc))
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync pProgress.queryInterfaceTo(aProgress);
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync }
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync else if (pTask != NULL)
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync delete pTask;
76364cddabfeb143dad91862d41a5638d8860b25vboxsync
76364cddabfeb143dad91862d41a5638d8860b25vboxsync return rc;
76364cddabfeb143dad91862d41a5638d8860b25vboxsync}
76364cddabfeb143dad91862d41a5638d8860b25vboxsync
76364cddabfeb143dad91862d41a5638d8860b25vboxsyncSTDMETHODIMP Medium::Resize(ULONG64 aLogicalSize, IProgress **aProgress)
76364cddabfeb143dad91862d41a5638d8860b25vboxsync{
76364cddabfeb143dad91862d41a5638d8860b25vboxsync CheckComArgOutPointerValid(aProgress);
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync
1e1273b11e17928ec3c3a8fff45121aa7a169413vboxsync AutoCaller autoCaller(this);
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
1e1273b11e17928ec3c3a8fff45121aa7a169413vboxsync
1e1273b11e17928ec3c3a8fff45121aa7a169413vboxsync NOREF(aLogicalSize);
b5ad839a3757b305d4e98d7264da2b53c9cd27f0vboxsync NOREF(aProgress);
b5ad839a3757b305d4e98d7264da2b53c9cd27f0vboxsync ReturnComNotImplemented();
b5ad839a3757b305d4e98d7264da2b53c9cd27f0vboxsync}
b5ad839a3757b305d4e98d7264da2b53c9cd27f0vboxsync
b5ad839a3757b305d4e98d7264da2b53c9cd27f0vboxsyncSTDMETHODIMP Medium::Reset(IProgress **aProgress)
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync{
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync CheckComArgOutPointerValid(aProgress);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync AutoCaller autoCaller(this);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
cba6719bd64ec749967bbe931230452664109857vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync HRESULT rc = S_OK;
1e1273b11e17928ec3c3a8fff45121aa7a169413vboxsync ComObjPtr <Progress> pProgress;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync Medium::Task *pTask = NULL;
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync
1e1273b11e17928ec3c3a8fff45121aa7a169413vboxsync try
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync {
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* canClose() needs the tree lock */
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync AutoMultiWriteLock2 multilock(&m->pVirtualBox->getMediaTreeLockHandle(),
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync this->lockHandle()
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync COMMA_LOCKVAL_SRC_POS);
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync LogFlowThisFunc(("ENTER for medium %s\n", m->strLocationFull.c_str()));
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync if (m->pParent.isNull())
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync throw setError(VBOX_E_NOT_SUPPORTED,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync tr("Hard disk '%s' is not differencing"),
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync m->strLocationFull.raw());
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync rc = canClose();
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync if (FAILED(rc))
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync throw rc;
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync
090d729e786b999dc285f8ea267f9effd1319544vboxsync /* Build the medium lock list. */
61d064a54f03596920c3918f58ecc7764074a5d8vboxsync MediumLockList *pMediumLockList(new MediumLockList());
16a9adc14900ca18e6909679a579f6833425e030vboxsync rc = createMediumLockList(true /* fFailIfInaccessible */,
16a9adc14900ca18e6909679a579f6833425e030vboxsync true /* fMediumLockWrite */,
1e1273b11e17928ec3c3a8fff45121aa7a169413vboxsync NULL,
16a9adc14900ca18e6909679a579f6833425e030vboxsync *pMediumLockList);
16a9adc14900ca18e6909679a579f6833425e030vboxsync if (FAILED(rc))
203cad92999b4792bf61b4b65e1e2abfe08f5664vboxsync {
c5abe3ea9c7ac6dec34f42af30612534bea951ffvboxsync delete pMediumLockList;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync throw rc;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync }
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync
1fdf058ef3f645ee13c9957807e401ac3c9bc65bvboxsync rc = pMediumLockList->Lock();
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync if (FAILED(rc))
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync {
16a9adc14900ca18e6909679a579f6833425e030vboxsync delete pMediumLockList;
c5abe3ea9c7ac6dec34f42af30612534bea951ffvboxsync throw setError(rc,
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync tr("Failed to lock media when resetting '%s'"),
e18d16f31765f000e2a4a111a3df6d211cd825f1vboxsync getLocationFull().raw());
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync }
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync pProgress.createObject();
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync rc = pProgress->init(m->pVirtualBox,
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync static_cast<IMedium*>(this),
e2ebb3d022edb845fd1158d6338e3def1d0e2159vboxsync BstrFmt(tr("Resetting differencing hard disk '%s'"), m->strLocationFull.raw()),
e2ebb3d022edb845fd1158d6338e3def1d0e2159vboxsync FALSE /* aCancelable */);
47579c4cc64e7dff9b4de48841a2c4df3b96ab38vboxsync if (FAILED(rc))
47579c4cc64e7dff9b4de48841a2c4df3b96ab38vboxsync throw rc;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsync /* setup task object to carry out the operation asynchronously */
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync pTask = new Medium::ResetTask(this, pProgress, pMediumLockList);
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync rc = pTask->rc();
fc78e01f665145ab3641c5f8095e9ae984ddcb84vboxsync AssertComRC(rc);
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync if (FAILED(rc))
9496f2d398b49813176939d7a339ae513d5175efvboxsync throw rc;
9496f2d398b49813176939d7a339ae513d5175efvboxsync }
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync catch (HRESULT aRC) { rc = aRC; }
68a4ee3a31a0807abd03eae881c1bbaf4d42ee6dvboxsync
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync if (SUCCEEDED(rc))
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync {
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync rc = startThread(pTask);
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsync if (SUCCEEDED(rc))
9496f2d398b49813176939d7a339ae513d5175efvboxsync pProgress.queryInterfaceTo(aProgress);
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync }
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync else
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync {
cab115cfa31c584def7069312a1e23c3fc88533bvboxsync /* Note: on success, the task will unlock this */
cab115cfa31c584def7069312a1e23c3fc88533bvboxsync {
cab115cfa31c584def7069312a1e23c3fc88533bvboxsync AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
cab115cfa31c584def7069312a1e23c3fc88533bvboxsync HRESULT rc2 = UnlockWrite(NULL);
cab115cfa31c584def7069312a1e23c3fc88533bvboxsync AssertComRC(rc2);
9496f2d398b49813176939d7a339ae513d5175efvboxsync }
da3503c04ce76e653401396fe2795a9bc2427a1dvboxsync if (pTask != NULL)
9496f2d398b49813176939d7a339ae513d5175efvboxsync delete pTask;
10e818af327731667e40ed25ee3e70ab5ea2cc4cvboxsync }
10e818af327731667e40ed25ee3e70ab5ea2cc4cvboxsync
10e818af327731667e40ed25ee3e70ab5ea2cc4cvboxsync LogFlowThisFunc(("LEAVE, rc=%Rhrc\n", rc));
10e818af327731667e40ed25ee3e70ab5ea2cc4cvboxsync
10e818af327731667e40ed25ee3e70ab5ea2cc4cvboxsync return rc;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync}
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync////////////////////////////////////////////////////////////////////////////////
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync//
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync// Medium internal methods
27b178e99b06a68ef52353b15bc647674d2006bcvboxsync//
009d45aa55691312278d41edb20154dc208d9cd8vboxsync////////////////////////////////////////////////////////////////////////////////
e2ebb3d022edb845fd1158d6338e3def1d0e2159vboxsync
c13422b6c2690d4243041112362ef95e0ac23e79vboxsync/**
6437cb19ad6d607a74ccf8d8f25c7e7af761b316vboxsync * Internal method to return the medium's parent medium. Must have caller + locking!
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * @return
c28fa006ba669ad8f26ae31d00a338379c04ea1bvboxsync */
ee00a0b29854e7f513198772bccb6650f6dd2184vboxsyncconst ComObjPtr<Medium>& Medium::getParent() const
090d729e786b999dc285f8ea267f9effd1319544vboxsync{
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync return m->pParent;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync}
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/**
c28fa006ba669ad8f26ae31d00a338379c04ea1bvboxsync * Internal method to return the medium's list of child media. Must have caller + locking!
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * @return
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync */
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsyncconst MediaList& Medium::getChildren() const
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync{
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync return m->llChildren;
61d064a54f03596920c3918f58ecc7764074a5d8vboxsync}
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync
009d45aa55691312278d41edb20154dc208d9cd8vboxsync/**
6437cb19ad6d607a74ccf8d8f25c7e7af761b316vboxsync * Internal method to return the medium's GUID. Must have caller + locking!
6437cb19ad6d607a74ccf8d8f25c7e7af761b316vboxsync * @return
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncconst Guid& Medium::getId() const
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync{
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync return m->id;
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync}
16a9adc14900ca18e6909679a579f6833425e030vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync/**
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * Internal method to return the medium's GUID. Must have caller + locking!
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * @return
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncMediumState_T Medium::getState() const
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync{
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync return m->state;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync}
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
c28fa006ba669ad8f26ae31d00a338379c04ea1bvboxsync/**
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync * Internal method to return the medium's location. Must have caller + locking!
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync * @return
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync */
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsyncconst Utf8Str& Medium::getLocation() const
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync{
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync return m->strLocation;
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync}
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync/**
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync * Internal method to return the medium's full location. Must have caller + locking!
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync * @return
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync */
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsyncconst Utf8Str& Medium::getLocationFull() const
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync{
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync return m->strLocationFull;
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync}
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync/**
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync * Internal method to return the medium's format string. Must have caller + locking!
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync * @return
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync */
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsyncconst Utf8Str& Medium::getFormat() const
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync{
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync return m->strFormat;
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync}
24a0cc1776a88752cc25446a98e2a3881e623216vboxsync
24a0cc1776a88752cc25446a98e2a3881e623216vboxsync/**
24a0cc1776a88752cc25446a98e2a3881e623216vboxsync * Internal method to return the medium's format object. Must have caller + locking!
24a0cc1776a88752cc25446a98e2a3881e623216vboxsync * @return
24a0cc1776a88752cc25446a98e2a3881e623216vboxsync */
24a0cc1776a88752cc25446a98e2a3881e623216vboxsyncconst ComObjPtr<MediumFormat> & Medium::getMediumFormat() const
24a0cc1776a88752cc25446a98e2a3881e623216vboxsync{
24a0cc1776a88752cc25446a98e2a3881e623216vboxsync return m->formatObj;
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync}
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync/**
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync * Internal method to return the medium's size. Must have caller + locking!
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync * @return
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync */
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsyncuint64_t Medium::getSize() const
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync{
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync return m->size;
16a9adc14900ca18e6909679a579f6833425e030vboxsync}
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync/**
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync * Adds the given machine and optionally the snapshot to the list of the objects
61d064a54f03596920c3918f58ecc7764074a5d8vboxsync * this image is attached to.
61d064a54f03596920c3918f58ecc7764074a5d8vboxsync *
61d064a54f03596920c3918f58ecc7764074a5d8vboxsync * @param aMachineId Machine ID.
61d064a54f03596920c3918f58ecc7764074a5d8vboxsync * @param aSnapshotId Snapshot ID; when non-empty, adds a snapshot attachment.
61d064a54f03596920c3918f58ecc7764074a5d8vboxsync */
61d064a54f03596920c3918f58ecc7764074a5d8vboxsyncHRESULT Medium::attachTo(const Guid &aMachineId,
61d064a54f03596920c3918f58ecc7764074a5d8vboxsync const Guid &aSnapshotId /*= Guid::Empty*/)
61d064a54f03596920c3918f58ecc7764074a5d8vboxsync{
61d064a54f03596920c3918f58ecc7764074a5d8vboxsync AssertReturn(!aMachineId.isEmpty(), E_FAIL);
44fc72ff17b23a9b970505fcf8d6da1019ddcec5vboxsync
27b178e99b06a68ef52353b15bc647674d2006bcvboxsync LogFlowThisFunc(("ENTER, aMachineId: {%RTuuid}, aSnapshotId: {%RTuuid}\n", aMachineId.raw(), aSnapshotId.raw()));
27b178e99b06a68ef52353b15bc647674d2006bcvboxsync
27b178e99b06a68ef52353b15bc647674d2006bcvboxsync AutoCaller autoCaller(this);
27b178e99b06a68ef52353b15bc647674d2006bcvboxsync AssertComRCReturnRC(autoCaller.rc());
27b178e99b06a68ef52353b15bc647674d2006bcvboxsync
27b178e99b06a68ef52353b15bc647674d2006bcvboxsync AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
16a9adc14900ca18e6909679a579f6833425e030vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync switch (m->state)
16a9adc14900ca18e6909679a579f6833425e030vboxsync {
16a9adc14900ca18e6909679a579f6833425e030vboxsync case MediumState_Created:
16a9adc14900ca18e6909679a579f6833425e030vboxsync case MediumState_Inaccessible:
16a9adc14900ca18e6909679a579f6833425e030vboxsync case MediumState_LockedRead:
16a9adc14900ca18e6909679a579f6833425e030vboxsync case MediumState_LockedWrite:
16a9adc14900ca18e6909679a579f6833425e030vboxsync break;
16a9adc14900ca18e6909679a579f6833425e030vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync default:
16a9adc14900ca18e6909679a579f6833425e030vboxsync return setStateError();
16a9adc14900ca18e6909679a579f6833425e030vboxsync }
16a9adc14900ca18e6909679a579f6833425e030vboxsync
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync if (m->numCreateDiffTasks > 0)
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync return setError(E_FAIL,
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync tr("Cannot attach hard disk '%s' {%RTuuid}: %u differencing child hard disk(s) are being created"),
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync m->strLocationFull.raw(),
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync m->id.raw(),
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync m->numCreateDiffTasks);
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync BackRefList::iterator it = std::find_if(m->backRefs.begin(),
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync m->backRefs.end(),
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync BackRef::EqualsTo(aMachineId));
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync if (it == m->backRefs.end())
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync {
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync BackRef ref(aMachineId, aSnapshotId);
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync m->backRefs.push_back(ref);
009d45aa55691312278d41edb20154dc208d9cd8vboxsync
009d45aa55691312278d41edb20154dc208d9cd8vboxsync return S_OK;
009d45aa55691312278d41edb20154dc208d9cd8vboxsync }
009d45aa55691312278d41edb20154dc208d9cd8vboxsync
009d45aa55691312278d41edb20154dc208d9cd8vboxsync // if the caller has not supplied a snapshot ID, then we're attaching
009d45aa55691312278d41edb20154dc208d9cd8vboxsync // to a machine a medium which represents the machine's current state,
009d45aa55691312278d41edb20154dc208d9cd8vboxsync // so set the flag
b5ad839a3757b305d4e98d7264da2b53c9cd27f0vboxsync if (aSnapshotId.isEmpty())
b5ad839a3757b305d4e98d7264da2b53c9cd27f0vboxsync {
b5ad839a3757b305d4e98d7264da2b53c9cd27f0vboxsync /* sanity: no duplicate attachments */
b5ad839a3757b305d4e98d7264da2b53c9cd27f0vboxsync AssertReturn(!it->fInCurState, E_FAIL);
b5ad839a3757b305d4e98d7264da2b53c9cd27f0vboxsync it->fInCurState = true;
b5ad839a3757b305d4e98d7264da2b53c9cd27f0vboxsync
b5ad839a3757b305d4e98d7264da2b53c9cd27f0vboxsync return S_OK;
b5ad839a3757b305d4e98d7264da2b53c9cd27f0vboxsync }
b5ad839a3757b305d4e98d7264da2b53c9cd27f0vboxsync
e2ebb3d022edb845fd1158d6338e3def1d0e2159vboxsync // otherwise: a snapshot medium is being attached
e2ebb3d022edb845fd1158d6338e3def1d0e2159vboxsync
e2ebb3d022edb845fd1158d6338e3def1d0e2159vboxsync /* sanity: no duplicate attachments */
e2ebb3d022edb845fd1158d6338e3def1d0e2159vboxsync for (BackRef::GuidList::const_iterator jt = it->llSnapshotIds.begin();
e2ebb3d022edb845fd1158d6338e3def1d0e2159vboxsync jt != it->llSnapshotIds.end();
e2ebb3d022edb845fd1158d6338e3def1d0e2159vboxsync ++jt)
e2ebb3d022edb845fd1158d6338e3def1d0e2159vboxsync {
e2ebb3d022edb845fd1158d6338e3def1d0e2159vboxsync const Guid &idOldSnapshot = *jt;
e2ebb3d022edb845fd1158d6338e3def1d0e2159vboxsync
e2ebb3d022edb845fd1158d6338e3def1d0e2159vboxsync if (idOldSnapshot == aSnapshotId)
e2ebb3d022edb845fd1158d6338e3def1d0e2159vboxsync {
e2ebb3d022edb845fd1158d6338e3def1d0e2159vboxsync#ifdef DEBUG
e2ebb3d022edb845fd1158d6338e3def1d0e2159vboxsync dumpBackRefs();
c13422b6c2690d4243041112362ef95e0ac23e79vboxsync#endif
c13422b6c2690d4243041112362ef95e0ac23e79vboxsync return setError(E_FAIL,
c13422b6c2690d4243041112362ef95e0ac23e79vboxsync tr("Cannot attach medium '%s' {%RTuuid} from snapshot '%RTuuid': medium is already in use by this snapshot!"),
c13422b6c2690d4243041112362ef95e0ac23e79vboxsync m->strLocationFull.raw(),
4bc80d07c812dc7ce2b5a329b489cfdb722c9013vboxsync m->id.raw(),
c13422b6c2690d4243041112362ef95e0ac23e79vboxsync aSnapshotId.raw(),
c13422b6c2690d4243041112362ef95e0ac23e79vboxsync idOldSnapshot.raw());
6437cb19ad6d607a74ccf8d8f25c7e7af761b316vboxsync }
6437cb19ad6d607a74ccf8d8f25c7e7af761b316vboxsync }
6437cb19ad6d607a74ccf8d8f25c7e7af761b316vboxsync
6437cb19ad6d607a74ccf8d8f25c7e7af761b316vboxsync it->llSnapshotIds.push_back(aSnapshotId);
6437cb19ad6d607a74ccf8d8f25c7e7af761b316vboxsync it->fInCurState = false;
6437cb19ad6d607a74ccf8d8f25c7e7af761b316vboxsync
6437cb19ad6d607a74ccf8d8f25c7e7af761b316vboxsync LogFlowThisFuncLeave();
ee00a0b29854e7f513198772bccb6650f6dd2184vboxsync
ee00a0b29854e7f513198772bccb6650f6dd2184vboxsync return S_OK;
ee00a0b29854e7f513198772bccb6650f6dd2184vboxsync}
ee00a0b29854e7f513198772bccb6650f6dd2184vboxsync
ee00a0b29854e7f513198772bccb6650f6dd2184vboxsync/**
ee00a0b29854e7f513198772bccb6650f6dd2184vboxsync * Removes the given machine and optionally the snapshot from the list of the
ee00a0b29854e7f513198772bccb6650f6dd2184vboxsync * objects this image is attached to.
ee00a0b29854e7f513198772bccb6650f6dd2184vboxsync *
ee00a0b29854e7f513198772bccb6650f6dd2184vboxsync * @param aMachineId Machine ID.
ee00a0b29854e7f513198772bccb6650f6dd2184vboxsync * @param aSnapshotId Snapshot ID; when non-empty, removes the snapshot
ee00a0b29854e7f513198772bccb6650f6dd2184vboxsync * attachment.
ee00a0b29854e7f513198772bccb6650f6dd2184vboxsync */
ee00a0b29854e7f513198772bccb6650f6dd2184vboxsyncHRESULT Medium::detachFrom(const Guid &aMachineId,
ee00a0b29854e7f513198772bccb6650f6dd2184vboxsync const Guid &aSnapshotId /*= Guid::Empty*/)
ee00a0b29854e7f513198772bccb6650f6dd2184vboxsync{
ee00a0b29854e7f513198772bccb6650f6dd2184vboxsync AssertReturn(!aMachineId.isEmpty(), E_FAIL);
ee00a0b29854e7f513198772bccb6650f6dd2184vboxsync
ee00a0b29854e7f513198772bccb6650f6dd2184vboxsync AutoCaller autoCaller(this);
ee00a0b29854e7f513198772bccb6650f6dd2184vboxsync AssertComRCReturnRC(autoCaller.rc());
ee00a0b29854e7f513198772bccb6650f6dd2184vboxsync
ee00a0b29854e7f513198772bccb6650f6dd2184vboxsync AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
ee00a0b29854e7f513198772bccb6650f6dd2184vboxsync
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync BackRefList::iterator it =
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync std::find_if(m->backRefs.begin(), m->backRefs.end(),
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync BackRef::EqualsTo(aMachineId));
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync AssertReturn(it != m->backRefs.end(), E_FAIL);
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync if (aSnapshotId.isEmpty())
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync {
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync /* remove the current state attachment */
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync it->fInCurState = false;
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync }
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync else
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync {
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync /* remove the snapshot attachment */
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync BackRef::GuidList::iterator jt =
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync std::find(it->llSnapshotIds.begin(), it->llSnapshotIds.end(), aSnapshotId);
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync AssertReturn(jt != it->llSnapshotIds.end(), E_FAIL);
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync it->llSnapshotIds.erase(jt);
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync }
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync /* if the backref becomes empty, remove it */
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync if (it->fInCurState == false && it->llSnapshotIds.size() == 0)
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync m->backRefs.erase(it);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync return S_OK;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync}
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/**
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * Internal method to return the medium's list of backrefs. Must have caller + locking!
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * @return
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync */
16a9adc14900ca18e6909679a579f6833425e030vboxsyncconst Guid* Medium::getFirstMachineBackrefId() const
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync{
b7a5b3f9f9ecce32ddacf8404c625ce0451bbdc1vboxsync if (!m->backRefs.size())
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync return NULL;
61b5982fad4660d0fe3dd6ceba9eda85eb32f7e8vboxsync
61b5982fad4660d0fe3dd6ceba9eda85eb32f7e8vboxsync return &m->backRefs.front().machineId;
61b5982fad4660d0fe3dd6ceba9eda85eb32f7e8vboxsync}
61b5982fad4660d0fe3dd6ceba9eda85eb32f7e8vboxsync
61b5982fad4660d0fe3dd6ceba9eda85eb32f7e8vboxsyncconst Guid* Medium::getFirstMachineBackrefSnapshotId() const
61b5982fad4660d0fe3dd6ceba9eda85eb32f7e8vboxsync{
61b5982fad4660d0fe3dd6ceba9eda85eb32f7e8vboxsync if (!m->backRefs.size())
61b5982fad4660d0fe3dd6ceba9eda85eb32f7e8vboxsync return NULL;
61b5982fad4660d0fe3dd6ceba9eda85eb32f7e8vboxsync
61b5982fad4660d0fe3dd6ceba9eda85eb32f7e8vboxsync const BackRef &ref = m->backRefs.front();
c8cedf818a53e003ce5a59c552d2f15c1b51f64cvboxsync if (!ref.llSnapshotIds.size())
c8cedf818a53e003ce5a59c552d2f15c1b51f64cvboxsync return NULL;
c8cedf818a53e003ce5a59c552d2f15c1b51f64cvboxsync
c8cedf818a53e003ce5a59c552d2f15c1b51f64cvboxsync return &ref.llSnapshotIds.front();
c8cedf818a53e003ce5a59c552d2f15c1b51f64cvboxsync}
c8cedf818a53e003ce5a59c552d2f15c1b51f64cvboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync#ifdef DEBUG
16a9adc14900ca18e6909679a579f6833425e030vboxsync/**
16a9adc14900ca18e6909679a579f6833425e030vboxsync * Debugging helper that gets called after VirtualBox initialization that writes all
16a9adc14900ca18e6909679a579f6833425e030vboxsync * machine backreferences to the debug log.
16a9adc14900ca18e6909679a579f6833425e030vboxsync */
16a9adc14900ca18e6909679a579f6833425e030vboxsyncvoid Medium::dumpBackRefs()
16a9adc14900ca18e6909679a579f6833425e030vboxsync{
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync AutoCaller autoCaller(this);
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync LogFlowThisFunc(("Dumping backrefs for medium '%s':\n", m->strLocationFull.raw()));
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync for (BackRefList::iterator it2 = m->backRefs.begin();
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync it2 != m->backRefs.end();
16a9adc14900ca18e6909679a579f6833425e030vboxsync ++it2)
16a9adc14900ca18e6909679a579f6833425e030vboxsync {
16a9adc14900ca18e6909679a579f6833425e030vboxsync const BackRef &ref = *it2;
16a9adc14900ca18e6909679a579f6833425e030vboxsync LogFlowThisFunc((" Backref from machine {%RTuuid} (fInCurState: %d)\n", ref.machineId.raw(), ref.fInCurState));
16a9adc14900ca18e6909679a579f6833425e030vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync for (BackRef::GuidList::const_iterator jt2 = it2->llSnapshotIds.begin();
16a9adc14900ca18e6909679a579f6833425e030vboxsync jt2 != it2->llSnapshotIds.end();
bbede9c189def47a9880f0ffb03c0c230c774185vboxsync ++jt2)
a3369a746b56a8966dd78619f4d191c9662f400dvboxsync {
a3369a746b56a8966dd78619f4d191c9662f400dvboxsync const Guid &id = *jt2;
ee00a0b29854e7f513198772bccb6650f6dd2184vboxsync LogFlowThisFunc((" Backref from snapshot {%RTuuid}\n", id.raw()));
a3369a746b56a8966dd78619f4d191c9662f400dvboxsync }
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync }
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync}
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync#endif
d5ea45cc92d7f1d3ade8189944531f665bfe8ed5vboxsync
5d0d754550d06b7d59a935e59caaf814462d53ccvboxsync/**
5d0d754550d06b7d59a935e59caaf814462d53ccvboxsync * Checks if the given change of \a aOldPath to \a aNewPath affects the location
6437cb19ad6d607a74ccf8d8f25c7e7af761b316vboxsync * of this media and updates it if necessary to reflect the new location.
6437cb19ad6d607a74ccf8d8f25c7e7af761b316vboxsync *
16a9adc14900ca18e6909679a579f6833425e030vboxsync * @param aOldPath Old path (full).
b7a5b3f9f9ecce32ddacf8404c625ce0451bbdc1vboxsync * @param aNewPath New path (full).
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync *
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync * @note Locks this object for writing.
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync */
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsyncHRESULT Medium::updatePath(const char *aOldPath, const char *aNewPath)
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync{
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync AssertReturn(aOldPath, E_FAIL);
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync AssertReturn(aNewPath, E_FAIL);
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync AutoCaller autoCaller(this);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
b7a5b3f9f9ecce32ddacf8404c625ce0451bbdc1vboxsync LogFlowThisFunc(("locationFull.before='%s'\n", m->strLocationFull.raw()));
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync const char *pcszMediumPath = m->strLocationFull.c_str();
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync if (RTPathStartsWith(pcszMediumPath, aOldPath))
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync {
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync Utf8Str newPath = Utf8StrFmt("%s%s",
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync aNewPath,
b7a5b3f9f9ecce32ddacf8404c625ce0451bbdc1vboxsync pcszMediumPath + strlen(aOldPath));
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync Utf8Str path = newPath;
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync m->pVirtualBox->calculateRelativePath(path, path);
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync unconst(m->strLocationFull) = newPath;
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync unconst(m->strLocation) = path;
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync LogFlowThisFunc(("locationFull.after='%s'\n", m->strLocationFull.raw()));
16a9adc14900ca18e6909679a579f6833425e030vboxsync }
16a9adc14900ca18e6909679a579f6833425e030vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync return S_OK;
16a9adc14900ca18e6909679a579f6833425e030vboxsync}
16a9adc14900ca18e6909679a579f6833425e030vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync/**
16a9adc14900ca18e6909679a579f6833425e030vboxsync * Checks if the given change of \a aOldPath to \a aNewPath affects the location
16a9adc14900ca18e6909679a579f6833425e030vboxsync * of this hard disk or any its child and updates the paths if necessary to
16a9adc14900ca18e6909679a579f6833425e030vboxsync * reflect the new location.
16a9adc14900ca18e6909679a579f6833425e030vboxsync *
16a9adc14900ca18e6909679a579f6833425e030vboxsync * @param aOldPath Old path (full).
16a9adc14900ca18e6909679a579f6833425e030vboxsync * @param aNewPath New path (full).
16a9adc14900ca18e6909679a579f6833425e030vboxsync *
16a9adc14900ca18e6909679a579f6833425e030vboxsync * @note Locks the medium tree for reading, this object and all children for writing.
16a9adc14900ca18e6909679a579f6833425e030vboxsync */
16a9adc14900ca18e6909679a579f6833425e030vboxsyncvoid Medium::updatePaths(const char *aOldPath, const char *aNewPath)
16a9adc14900ca18e6909679a579f6833425e030vboxsync{
16a9adc14900ca18e6909679a579f6833425e030vboxsync AssertReturnVoid(aOldPath);
16a9adc14900ca18e6909679a579f6833425e030vboxsync AssertReturnVoid(aNewPath);
16a9adc14900ca18e6909679a579f6833425e030vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync AutoCaller autoCaller(this);
16a9adc14900ca18e6909679a579f6833425e030vboxsync AssertComRCReturnVoid(autoCaller.rc());
16a9adc14900ca18e6909679a579f6833425e030vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync /* we access children() */
16a9adc14900ca18e6909679a579f6833425e030vboxsync AutoReadLock treeLock(m->pVirtualBox->getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS);
16a9adc14900ca18e6909679a579f6833425e030vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
16a9adc14900ca18e6909679a579f6833425e030vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync updatePath(aOldPath, aNewPath);
16a9adc14900ca18e6909679a579f6833425e030vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync /* update paths of all children */
16a9adc14900ca18e6909679a579f6833425e030vboxsync for (MediaList::const_iterator it = getChildren().begin();
16a9adc14900ca18e6909679a579f6833425e030vboxsync it != getChildren().end();
16a9adc14900ca18e6909679a579f6833425e030vboxsync ++it)
16a9adc14900ca18e6909679a579f6833425e030vboxsync {
16a9adc14900ca18e6909679a579f6833425e030vboxsync (*it)->updatePaths(aOldPath, aNewPath);
16a9adc14900ca18e6909679a579f6833425e030vboxsync }
16a9adc14900ca18e6909679a579f6833425e030vboxsync}
16a9adc14900ca18e6909679a579f6833425e030vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync/**
670b83d458bceb92123155b5b47a39b9d24e3266vboxsync * Returns the base hard disk of the hard disk chain this hard disk is part of.
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync *
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync * The base hard disk is found by walking up the parent-child relationship axis.
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync * If the hard disk doesn't have a parent (i.e. it's a base hard disk), it
baacecc94a2d23b6f5086739c08cf06d6b357d0avboxsync * returns itself in response to this method.
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync *
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync * @param aLevel Where to store the number of ancestors of this hard disk
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync * (zero for the base), may be @c NULL.
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync *
1741b757f7a570a7e6d48db46c3f4cd50f2ee296vboxsync * @note Locks medium tree for reading.
1741b757f7a570a7e6d48db46c3f4cd50f2ee296vboxsync */
203cad92999b4792bf61b4b65e1e2abfe08f5664vboxsyncComObjPtr<Medium> Medium::getBase(uint32_t *aLevel /*= NULL*/)
1741b757f7a570a7e6d48db46c3f4cd50f2ee296vboxsync{
203cad92999b4792bf61b4b65e1e2abfe08f5664vboxsync ComObjPtr<Medium> pBase;
1741b757f7a570a7e6d48db46c3f4cd50f2ee296vboxsync uint32_t level;
1741b757f7a570a7e6d48db46c3f4cd50f2ee296vboxsync
203cad92999b4792bf61b4b65e1e2abfe08f5664vboxsync AutoCaller autoCaller(this);
203cad92999b4792bf61b4b65e1e2abfe08f5664vboxsync AssertReturn(autoCaller.isOk(), pBase);
203cad92999b4792bf61b4b65e1e2abfe08f5664vboxsync
c5abe3ea9c7ac6dec34f42af30612534bea951ffvboxsync /* we access mParent */
c5abe3ea9c7ac6dec34f42af30612534bea951ffvboxsync AutoReadLock treeLock(m->pVirtualBox->getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS);
d1aab951b0bd1de1a8a51daca46fce06daaed8d7vboxsync
d1aab951b0bd1de1a8a51daca46fce06daaed8d7vboxsync pBase = this;
d1aab951b0bd1de1a8a51daca46fce06daaed8d7vboxsync level = 0;
d1aab951b0bd1de1a8a51daca46fce06daaed8d7vboxsync
1741b757f7a570a7e6d48db46c3f4cd50f2ee296vboxsync if (m->pParent)
1741b757f7a570a7e6d48db46c3f4cd50f2ee296vboxsync {
c0a370e600bb60153a269fb32b5f709347c35768vboxsync for (;;)
c0a370e600bb60153a269fb32b5f709347c35768vboxsync {
c0a370e600bb60153a269fb32b5f709347c35768vboxsync AutoCaller baseCaller(pBase);
c0a370e600bb60153a269fb32b5f709347c35768vboxsync AssertReturn(baseCaller.isOk(), pBase);
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync if (pBase->m->pParent.isNull())
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync break;
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync pBase = pBase->m->pParent;
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync ++level;
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync }
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync }
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync if (aLevel != NULL)
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync *aLevel = level;
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync return pBase;
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync}
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync/**
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync * Returns @c true if this hard disk cannot be modified because it has
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync * dependants (children) or is part of the snapshot. Related to the hard disk
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync * type and posterity, not to the current media state.
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync *
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync * @note Locks this object and medium tree for reading.
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync */
e4f367251aede667a6de69baa54ef9eb5f150871vboxsyncbool Medium::isReadOnly()
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync{
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync AutoCaller autoCaller(this);
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync AssertComRCReturn(autoCaller.rc(), false);
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync /* we access children */
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync AutoReadLock treeLock(m->pVirtualBox->getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS);
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync switch (m->type)
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync {
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync case MediumType_Normal:
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync {
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync if (getChildren().size() != 0)
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync return true;
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync for (BackRefList::const_iterator it = m->backRefs.begin();
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync it != m->backRefs.end(); ++it)
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync if (it->llSnapshotIds.size() != 0)
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync return true;
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync return false;
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync }
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync case MediumType_Immutable:
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync return true;
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync case MediumType_Writethrough:
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync case MediumType_Shareable:
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync return false;
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync default:
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync break;
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync }
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync AssertFailedReturn(false);
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync}
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync/**
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync * Saves hard disk data by appending a new <HardDisk> child node to the given
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync * parent node which can be either <HardDisks> or <HardDisk>.
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync *
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync * @param data Settings struct to be updated.
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync *
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync * @note Locks this object, medium tree and children for reading.
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync */
e4f367251aede667a6de69baa54ef9eb5f150871vboxsyncHRESULT Medium::saveSettings(settings::Medium &data)
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync{
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync AutoCaller autoCaller(this);
c0a370e600bb60153a269fb32b5f709347c35768vboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
c0a370e600bb60153a269fb32b5f709347c35768vboxsync
c0a370e600bb60153a269fb32b5f709347c35768vboxsync /* we access mParent */
c0a370e600bb60153a269fb32b5f709347c35768vboxsync AutoReadLock treeLock(m->pVirtualBox->getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS);
c0a370e600bb60153a269fb32b5f709347c35768vboxsync
c0a370e600bb60153a269fb32b5f709347c35768vboxsync AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
c0a370e600bb60153a269fb32b5f709347c35768vboxsync
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync data.uuid = m->id;
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync data.strLocation = m->strLocation;
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync data.strFormat = m->strFormat;
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync /* optional, only for diffs, default is false */
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync if (m->pParent)
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync data.fAutoReset = m->autoReset;
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync else
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync data.fAutoReset = false;
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync /* optional */
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync data.strDescription = m->strDescription;
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync /* optional properties */
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync data.properties.clear();
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync for (Data::PropertyMap::const_iterator it = m->properties.begin();
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync it != m->properties.end();
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync ++it)
c0a370e600bb60153a269fb32b5f709347c35768vboxsync {
c0a370e600bb60153a269fb32b5f709347c35768vboxsync /* only save properties that have non-default values */
c0a370e600bb60153a269fb32b5f709347c35768vboxsync if (!it->second.isEmpty())
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync {
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync Utf8Str name = it->first;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync Utf8Str value = it->second;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync data.properties[name] = value;
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync }
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync }
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* only for base hard disks */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync if (m->pParent.isNull())
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync data.hdType = m->type;
5d0d754550d06b7d59a935e59caaf814462d53ccvboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsync /* save all children */
61d064a54f03596920c3918f58ecc7764074a5d8vboxsync for (MediaList::const_iterator it = getChildren().begin();
61d064a54f03596920c3918f58ecc7764074a5d8vboxsync it != getChildren().end();
e2ebb3d022edb845fd1158d6338e3def1d0e2159vboxsync ++it)
e2ebb3d022edb845fd1158d6338e3def1d0e2159vboxsync {
c13422b6c2690d4243041112362ef95e0ac23e79vboxsync settings::Medium med;
c13422b6c2690d4243041112362ef95e0ac23e79vboxsync HRESULT rc = (*it)->saveSettings(med);
6437cb19ad6d607a74ccf8d8f25c7e7af761b316vboxsync AssertComRCReturnRC(rc);
6437cb19ad6d607a74ccf8d8f25c7e7af761b316vboxsync data.llChildren.push_back(med);
6437cb19ad6d607a74ccf8d8f25c7e7af761b316vboxsync }
9496f2d398b49813176939d7a339ae513d5175efvboxsync
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync return S_OK;
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync}
9496f2d398b49813176939d7a339ae513d5175efvboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsync/**
5d0d754550d06b7d59a935e59caaf814462d53ccvboxsync * Compares the location of this hard disk to the given location.
9496f2d398b49813176939d7a339ae513d5175efvboxsync *
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync * The comparison takes the location details into account. For example, if the
9496f2d398b49813176939d7a339ae513d5175efvboxsync * location is a file in the host's filesystem, a case insensitive comparison
9496f2d398b49813176939d7a339ae513d5175efvboxsync * will be performed for case insensitive filesystems.
e2ebb3d022edb845fd1158d6338e3def1d0e2159vboxsync *
e2ebb3d022edb845fd1158d6338e3def1d0e2159vboxsync * @param aLocation Location to compare to (as is).
e2ebb3d022edb845fd1158d6338e3def1d0e2159vboxsync * @param aResult Where to store the result of comparison: 0 if locations
e2ebb3d022edb845fd1158d6338e3def1d0e2159vboxsync * are equal, 1 if this object's location is greater than
e2ebb3d022edb845fd1158d6338e3def1d0e2159vboxsync * the specified location, and -1 otherwise.
e2ebb3d022edb845fd1158d6338e3def1d0e2159vboxsync */
e2ebb3d022edb845fd1158d6338e3def1d0e2159vboxsyncHRESULT Medium::compareLocationTo(const char *aLocation, int &aResult)
e2ebb3d022edb845fd1158d6338e3def1d0e2159vboxsync{
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync AutoCaller autoCaller(this);
e2ebb3d022edb845fd1158d6338e3def1d0e2159vboxsync AssertComRCReturnRC(autoCaller.rc());
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
e2ebb3d022edb845fd1158d6338e3def1d0e2159vboxsync
b7a5b3f9f9ecce32ddacf8404c625ce0451bbdc1vboxsync Utf8Str locationFull(m->strLocationFull);
6b223679d40f5e57e55e867e806a9f194e2cde12vboxsync
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync /// @todo NEWMEDIA delegate the comparison to the backend?
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync if (m->formatObj->capabilities() & MediumFormatCapabilities_File)
24a0cc1776a88752cc25446a98e2a3881e623216vboxsync {
d1bffa158f98ff3c18f7d085e7372c9ea00e9a43vboxsync Utf8Str location(aLocation);
24a0cc1776a88752cc25446a98e2a3881e623216vboxsync
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync /* For locations represented by files, append the default path if
d1bffa158f98ff3c18f7d085e7372c9ea00e9a43vboxsync * only the name is given, and then get the full path. */
6b223679d40f5e57e55e867e806a9f194e2cde12vboxsync if (!RTPathHavePath(aLocation))
6b223679d40f5e57e55e867e806a9f194e2cde12vboxsync {
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync location = Utf8StrFmt("%s%c%s",
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync m->pVirtualBox->getDefaultHardDiskFolder().raw(),
6b223679d40f5e57e55e867e806a9f194e2cde12vboxsync RTPATH_DELIMITER,
6b223679d40f5e57e55e867e806a9f194e2cde12vboxsync aLocation);
6b223679d40f5e57e55e867e806a9f194e2cde12vboxsync }
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync int vrc = m->pVirtualBox->calculateFullPath(location, location);
927320c7f81d3acdbccb5f3fea7548b4b7184b98vboxsync if (RT_FAILURE(vrc))
fdab0fffeebe7ad5dfee549841f0c5482de95c34vboxsync return setError(E_FAIL,
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync tr("Invalid hard disk storage file location '%s' (%Rrc)"),
9496f2d398b49813176939d7a339ae513d5175efvboxsync location.raw(),
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync vrc);
9496f2d398b49813176939d7a339ae513d5175efvboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsync aResult = RTPathCompare(locationFull.c_str(), location.c_str());
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync }
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync else
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync aResult = locationFull.compare(aLocation);
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync return S_OK;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync}
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
76364cddabfeb143dad91862d41a5638d8860b25vboxsync/**
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * Constructs a medium lock list for this medium. The lock is not taken.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync *
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * @note Locks the medium tree for reading.
6437cb19ad6d607a74ccf8d8f25c7e7af761b316vboxsync *
6437cb19ad6d607a74ccf8d8f25c7e7af761b316vboxsync * @param fFailIfInaccessible If true, this fails with an error if a medium is inaccessible. If false,
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync * inaccessible media are silently skipped and not locked (i.e. their state remains "Inaccessible");
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync * this is necessary for a VM's removable images on VM startup for which we do not want to fail.
1e1273b11e17928ec3c3a8fff45121aa7a169413vboxsync * @param fMediumLockWrite Whether to associate a write lock with this medium.
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync * @param pToBeParent Medium which will become the parent of this medium.
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync * @param mediumLockList Where to store the resulting list.
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync */
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsyncHRESULT Medium::createMediumLockList(bool fFailIfInaccessible,
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync bool fMediumLockWrite,
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync Medium *pToBeParent,
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync MediumLockList &mediumLockList)
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync{
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync AutoCaller autoCaller(this);
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync HRESULT rc = S_OK;
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync /* we access parent medium objects */
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync AutoReadLock treeLock(m->pVirtualBox->getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS);
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync /* paranoid sanity checking if the medium has a to-be parent medium */
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync if (pToBeParent)
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync {
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync ComAssertRet(getParent().isNull(), E_FAIL);
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync ComAssertRet(getChildren().size() == 0, E_FAIL);
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync }
e4f367251aede667a6de69baa54ef9eb5f150871vboxsync
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync ErrorInfoKeeper eik;
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync MultiResult mrc(S_OK);
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync ComObjPtr<Medium> pMedium = this;
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync while (!pMedium.isNull())
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync {
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync // need write lock for RefreshState if medium is inaccessible
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync AutoWriteLock alock(pMedium COMMA_LOCKVAL_SRC_POS);
1e1273b11e17928ec3c3a8fff45121aa7a169413vboxsync
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync /* Accessibility check must be first, otherwise locking interferes
1e1273b11e17928ec3c3a8fff45121aa7a169413vboxsync * with getting the medium state. Lock lists are not created for
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync * fun, and thus getting the image status is no luxury. */
681fd85cc7cd49e9cf66a917d6ae9ff36eb7d9e9vboxsync MediumState_T mediumState = pMedium->getState();
16a9adc14900ca18e6909679a579f6833425e030vboxsync if (mediumState == MediumState_Inaccessible)
16a9adc14900ca18e6909679a579f6833425e030vboxsync {
16a9adc14900ca18e6909679a579f6833425e030vboxsync rc = pMedium->RefreshState(&mediumState);
16a9adc14900ca18e6909679a579f6833425e030vboxsync if (FAILED(rc)) return rc;
16a9adc14900ca18e6909679a579f6833425e030vboxsync
16a9adc14900ca18e6909679a579f6833425e030vboxsync if (mediumState == MediumState_Inaccessible)
16a9adc14900ca18e6909679a579f6833425e030vboxsync {
16a9adc14900ca18e6909679a579f6833425e030vboxsync // ignore inaccessible ISO images and silently return S_OK,
16a9adc14900ca18e6909679a579f6833425e030vboxsync // otherwise VM startup (esp. restore) may fail without good reason
009d45aa55691312278d41edb20154dc208d9cd8vboxsync if (!fFailIfInaccessible)
009d45aa55691312278d41edb20154dc208d9cd8vboxsync return S_OK;
cab115cfa31c584def7069312a1e23c3fc88533bvboxsync
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync // otherwise report an error
203cad92999b4792bf61b4b65e1e2abfe08f5664vboxsync Bstr error;
009d45aa55691312278d41edb20154dc208d9cd8vboxsync rc = pMedium->COMGETTER(LastAccessError)(error.asOutParam());
009d45aa55691312278d41edb20154dc208d9cd8vboxsync if (FAILED(rc)) return rc;
cab115cfa31c584def7069312a1e23c3fc88533bvboxsync
cab115cfa31c584def7069312a1e23c3fc88533bvboxsync /* collect multiple errors */
cab115cfa31c584def7069312a1e23c3fc88533bvboxsync eik.restore();
cab115cfa31c584def7069312a1e23c3fc88533bvboxsync Assert(!error.isEmpty());
cab115cfa31c584def7069312a1e23c3fc88533bvboxsync mrc = setError(E_FAIL,
cab115cfa31c584def7069312a1e23c3fc88533bvboxsync "%ls",
cab115cfa31c584def7069312a1e23c3fc88533bvboxsync error.raw());
cab115cfa31c584def7069312a1e23c3fc88533bvboxsync // error message will be something like
cab115cfa31c584def7069312a1e23c3fc88533bvboxsync // "Could not open the medium ... VD: error VERR_FILE_NOT_FOUND opening image file ... (VERR_FILE_NOT_FOUND).
cab115cfa31c584def7069312a1e23c3fc88533bvboxsync eik.fetch();
cab115cfa31c584def7069312a1e23c3fc88533bvboxsync }
cab115cfa31c584def7069312a1e23c3fc88533bvboxsync }
009d45aa55691312278d41edb20154dc208d9cd8vboxsync
cab115cfa31c584def7069312a1e23c3fc88533bvboxsync if (pMedium == this)
cab115cfa31c584def7069312a1e23c3fc88533bvboxsync mediumLockList.Prepend(pMedium, fMediumLockWrite);
cab115cfa31c584def7069312a1e23c3fc88533bvboxsync else
cab115cfa31c584def7069312a1e23c3fc88533bvboxsync mediumLockList.Prepend(pMedium, false);
cab115cfa31c584def7069312a1e23c3fc88533bvboxsync
cab115cfa31c584def7069312a1e23c3fc88533bvboxsync pMedium = pMedium->getParent();
cab115cfa31c584def7069312a1e23c3fc88533bvboxsync if (pMedium.isNull() && pToBeParent)
cab115cfa31c584def7069312a1e23c3fc88533bvboxsync {
009d45aa55691312278d41edb20154dc208d9cd8vboxsync pMedium = pToBeParent;
cab115cfa31c584def7069312a1e23c3fc88533bvboxsync pToBeParent = NULL;
cab115cfa31c584def7069312a1e23c3fc88533bvboxsync }
cab115cfa31c584def7069312a1e23c3fc88533bvboxsync }
cab115cfa31c584def7069312a1e23c3fc88533bvboxsync
cab115cfa31c584def7069312a1e23c3fc88533bvboxsync return mrc;
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync}
cab115cfa31c584def7069312a1e23c3fc88533bvboxsync
cab115cfa31c584def7069312a1e23c3fc88533bvboxsync/**
cab115cfa31c584def7069312a1e23c3fc88533bvboxsync * Returns a preferred format for differencing hard disks.
cab115cfa31c584def7069312a1e23c3fc88533bvboxsync */
cab115cfa31c584def7069312a1e23c3fc88533bvboxsyncBstr Medium::preferredDiffFormat()
cab115cfa31c584def7069312a1e23c3fc88533bvboxsync{
cab115cfa31c584def7069312a1e23c3fc88533bvboxsync Utf8Str strFormat;
cab115cfa31c584def7069312a1e23c3fc88533bvboxsync
009d45aa55691312278d41edb20154dc208d9cd8vboxsync AutoCaller autoCaller(this);
cab115cfa31c584def7069312a1e23c3fc88533bvboxsync AssertComRCReturn(autoCaller.rc(), strFormat);
cab115cfa31c584def7069312a1e23c3fc88533bvboxsync
cab115cfa31c584def7069312a1e23c3fc88533bvboxsync /* m->strFormat is const, no need to lock */
cab115cfa31c584def7069312a1e23c3fc88533bvboxsync strFormat = m->strFormat;
cab115cfa31c584def7069312a1e23c3fc88533bvboxsync
009d45aa55691312278d41edb20154dc208d9cd8vboxsync /* check that our own format supports diffs */
009d45aa55691312278d41edb20154dc208d9cd8vboxsync if (!(m->formatObj->capabilities() & MediumFormatCapabilities_Differencing))
009d45aa55691312278d41edb20154dc208d9cd8vboxsync {
baacecc94a2d23b6f5086739c08cf06d6b357d0avboxsync /* use the default format if not */
baacecc94a2d23b6f5086739c08cf06d6b357d0avboxsync AutoReadLock propsLock(m->pVirtualBox->systemProperties() COMMA_LOCKVAL_SRC_POS);
baacecc94a2d23b6f5086739c08cf06d6b357d0avboxsync strFormat = m->pVirtualBox->getDefaultHardDiskFormat();
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync }
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync return strFormat;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync}
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync/**
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync * Returns the medium type. Must have caller + locking!
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync * @return
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsyncMediumType_T Medium::getType() const
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync{
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync return m->type;
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync}
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync// private methods
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync////////////////////////////////////////////////////////////////////////////////
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync/**
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync * Returns a short version of the location attribute.
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync *
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync * @note Must be called from under this object's read or write lock.
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync */
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsyncUtf8Str Medium::getName()
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync{
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync Utf8Str name = RTPathFilename(m->strLocationFull.c_str());
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync return name;
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync}
b7a5b3f9f9ecce32ddacf8404c625ce0451bbdc1vboxsync
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync/**
1e1273b11e17928ec3c3a8fff45121aa7a169413vboxsync * Sets the value of m->strLocation and calculates the value of m->strLocationFull.
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync *
1e1273b11e17928ec3c3a8fff45121aa7a169413vboxsync * Treats non-FS-path locations specially, and prepends the default hard disk
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync * folder if the given location string does not contain any path information
4a23807f02e9920d92c8449bd93d84501add460avboxsync * at all.
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync *
4a23807f02e9920d92c8449bd93d84501add460avboxsync * Also, if the specified location is a file path that ends with '/' then the
1189c7dde5d7f6c26f338ced3d40fc830b822e68vboxsync * file name part will be generated by this method automatically in the format
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * '{<uuid>}.<ext>' where <uuid> is a fresh UUID that this method will generate
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * and assign to this medium, and <ext> is the default extension for this
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * medium's storage format. Note that this procedure requires the media state to
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * be NotCreated and will return a failure otherwise.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync *
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * @param aLocation Location of the storage unit. If the location is a FS-path,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * then it can be relative to the VirtualBox home directory.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * @param aFormat Optional fallback format if it is an import and the format
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * cannot be determined.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync *
5b465a7c1237993faf8bb50120d247f3f0319adavboxsync * @note Must be called from under this object's write lock.
09127e6ed46502ff8a6a521713ee8ace53667683vboxsync */
ad77e3ec3cde24263bc7537575f5cae442bee3b1vboxsyncHRESULT Medium::setLocation(const Utf8Str &aLocation, const Utf8Str &aFormat)
ad77e3ec3cde24263bc7537575f5cae442bee3b1vboxsync{
ad77e3ec3cde24263bc7537575f5cae442bee3b1vboxsync AssertReturn(!aLocation.isEmpty(), E_FAIL);
ad77e3ec3cde24263bc7537575f5cae442bee3b1vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync AutoCaller autoCaller(this);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync AssertComRCReturnRC(autoCaller.rc());
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* formatObj may be null only when initializing from an existing path and
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * no format is known yet */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync AssertReturn( (!m->strFormat.isEmpty() && !m->formatObj.isNull())
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync || ( autoCaller.state() == InInit
ad48e47654d22f79b025dc4b21cb162cb123801avboxsync && m->state != MediumState_NotCreated
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync && m->id.isEmpty()
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync && m->strFormat.isEmpty()
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync && m->formatObj.isNull()),
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync E_FAIL);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync /* are we dealing with a new medium constructed using the existing
ad77e3ec3cde24263bc7537575f5cae442bee3b1vboxsync * location? */
ad77e3ec3cde24263bc7537575f5cae442bee3b1vboxsync bool isImport = m->strFormat.isEmpty();
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync if ( isImport
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync || ( (m->formatObj->capabilities() & MediumFormatCapabilities_File)
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync && !m->hostDrive))
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync {
63c12491acc2b8b95c8ac454f1c48b98eec8f7d8vboxsync Guid id;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync Utf8Str location(aLocation);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync if (m->state == MediumState_NotCreated)
cba6719bd64ec749967bbe931230452664109857vboxsync {
cba6719bd64ec749967bbe931230452664109857vboxsync /* must be a file (formatObj must be already known) */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync Assert(m->formatObj->capabilities() & MediumFormatCapabilities_File);
9496f2d398b49813176939d7a339ae513d5175efvboxsync
9496f2d398b49813176939d7a339ae513d5175efvboxsync if (RTPathFilename(location.c_str()) == NULL)
840653a285d6bb20fb3150f7c85313956ae4ddb7vboxsync {
cba6719bd64ec749967bbe931230452664109857vboxsync /* no file name is given (either an empty string or ends with a
cba6719bd64ec749967bbe931230452664109857vboxsync * slash), generate a new UUID + file name if the state allows
cba6719bd64ec749967bbe931230452664109857vboxsync * this */
cba6719bd64ec749967bbe931230452664109857vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync ComAssertMsgRet(!m->formatObj->fileExtensions().empty(),
cba6719bd64ec749967bbe931230452664109857vboxsync ("Must be at least one extension if it is MediumFormatCapabilities_File\n"),
E_FAIL);
Bstr ext = m->formatObj->fileExtensions().front();
ComAssertMsgRet(!ext.isEmpty(),
("Default extension must not be empty\n"),
E_FAIL);
id.create();
location = Utf8StrFmt("%s{%RTuuid}.%ls",
location.raw(), id.raw(), ext.raw());
}
}
/* append the default folder if no path is given */
if (!RTPathHavePath(location.c_str()))
location = Utf8StrFmt("%s%c%s",
m->pVirtualBox->getDefaultHardDiskFolder().raw(),
RTPATH_DELIMITER,
location.raw());
/* get the full file name */
Utf8Str locationFull;
int vrc = m->pVirtualBox->calculateFullPath(location, locationFull);
if (RT_FAILURE(vrc))
return setError(VBOX_E_FILE_ERROR,
tr("Invalid medium storage file location '%s' (%Rrc)"),
location.raw(), vrc);
/* detect the backend from the storage unit if importing */
if (isImport)
{
char *backendName = NULL;
/* is it a file? */
{
RTFILE file;
vrc = RTFileOpen(&file, locationFull.c_str(), RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_NONE);
if (RT_SUCCESS(vrc))
RTFileClose(file);
}
if (RT_SUCCESS(vrc))
{
vrc = VDGetFormat(NULL, locationFull.c_str(), &backendName);
}
else if (vrc != VERR_FILE_NOT_FOUND && vrc != VERR_PATH_NOT_FOUND)
{
/* assume it's not a file, restore the original location */
location = locationFull = aLocation;
vrc = VDGetFormat(NULL, locationFull.c_str(), &backendName);
}
if (RT_FAILURE(vrc))
{
if (vrc == VERR_FILE_NOT_FOUND || vrc == VERR_PATH_NOT_FOUND)
return setError(VBOX_E_FILE_ERROR,
tr("Could not find file for the medium '%s' (%Rrc)"),
locationFull.raw(), vrc);
else if (aFormat.isEmpty())
return setError(VBOX_E_IPRT_ERROR,
tr("Could not get the storage format of the medium '%s' (%Rrc)"),
locationFull.raw(), vrc);
else
{
HRESULT rc = setFormat(Bstr(aFormat));
/* setFormat() must not fail since we've just used the backend so
* the format object must be there */
AssertComRCReturnRC(rc);
}
}
else
{
ComAssertRet(backendName != NULL && *backendName != '\0', E_FAIL);
HRESULT rc = setFormat(Bstr(backendName));
RTStrFree(backendName);
/* setFormat() must not fail since we've just used the backend so
* the format object must be there */
AssertComRCReturnRC(rc);
}
}
/* is it still a file? */
if (m->formatObj->capabilities() & MediumFormatCapabilities_File)
{
m->strLocation = location;
m->strLocationFull = locationFull;
if (m->state == MediumState_NotCreated)
{
/* assign a new UUID (this UUID will be used when calling
* VDCreateBase/VDCreateDiff as a wanted UUID). Note that we
* also do that if we didn't generate it to make sure it is
* either generated by us or reset to null */
unconst(m->id) = id;
}
}
else
{
m->strLocation = locationFull;
m->strLocationFull = locationFull;
}
}
else
{
m->strLocation = aLocation;
m->strLocationFull = aLocation;
}
return S_OK;
}
/**
* Queries information from the image file.
*
* As a result of this call, the accessibility state and data members such as
* size and description will be updated with the current information.
*
* @note This method may block during a system I/O call that checks storage
* accessibility.
*
* @note Locks medium tree for reading and writing (for new diff media checked
* for the first time). Locks mParent for reading. Locks this object for
* writing.
*/
HRESULT Medium::queryInfo()
{
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
if ( m->state != MediumState_Created
&& m->state != MediumState_Inaccessible
&& m->state != MediumState_LockedRead)
return E_FAIL;
HRESULT rc = S_OK;
int vrc = VINF_SUCCESS;
/* check if a blocking queryInfo() call is in progress on some other thread,
* and wait for it to finish if so instead of querying data ourselves */
if (m->queryInfoRunning)
{
Assert( m->state == MediumState_LockedRead
|| m->state == MediumState_LockedWrite);
alock.leave();
vrc = RTSemEventMultiWait(m->queryInfoSem, RT_INDEFINITE_WAIT);
alock.enter();
AssertRC(vrc);
return S_OK;
}
bool success = false;
Utf8Str lastAccessError;
/* are we dealing with a new medium constructed using the existing
* location? */
bool isImport = m->id.isEmpty();
unsigned flags = VD_OPEN_FLAGS_INFO;
/* Note that we don't use VD_OPEN_FLAGS_READONLY when opening new
* media because that would prevent necessary modifications
* when opening media of some third-party formats for the first
* time in VirtualBox (such as VMDK for which VDOpen() needs to
* generate an UUID if it is missing) */
if ( (m->hddOpenMode == OpenReadOnly)
|| !isImport
)
flags |= VD_OPEN_FLAGS_READONLY;
/* Lock the medium, which makes the behavior much more consistent */
if (flags & VD_OPEN_FLAGS_READONLY)
rc = LockRead(NULL);
else
rc = LockWrite(NULL);
if (FAILED(rc)) return rc;
/* Copies of the input state fields which are not read-only,
* as we're dropping the lock. CAUTION: be extremely careful what
* you do with the contents of this medium object, as you will
* create races if there are concurrent changes. */
Utf8Str format(m->strFormat);
Utf8Str location(m->strLocationFull);
ComObjPtr<MediumFormat> formatObj = m->formatObj;
/* "Output" values which can't be set because the lock isn't held
* at the time the values are determined. */
Guid mediumId = m->id;
uint64_t mediumSize = 0;
uint64_t mediumLogicalSize = 0;
/* leave the lock before a lengthy operation */
vrc = RTSemEventMultiReset(m->queryInfoSem);
AssertRCReturn(vrc, E_FAIL);
m->queryInfoRunning = true;
alock.leave();
try
{
/* skip accessibility checks for host drives */
if (m->hostDrive)
{
success = true;
throw S_OK;
}
PVBOXHDD hdd;
vrc = VDCreate(m->vdDiskIfaces, &hdd);
ComAssertRCThrow(vrc, E_FAIL);
try
{
/** @todo This kind of opening of images is assuming that diff
* images can be opened as base images. Should be documented if
* it must work for all medium format backends. */
vrc = VDOpen(hdd,
format.c_str(),
location.c_str(),
flags,
m->vdDiskIfaces);
if (RT_FAILURE(vrc))
{
lastAccessError = Utf8StrFmt(tr("Could not open the medium '%s'%s"),
location.c_str(), vdError(vrc).c_str());
throw S_OK;
}
if (formatObj->capabilities() & MediumFormatCapabilities_Uuid)
{
/* Modify the UUIDs if necessary. The associated fields are
* not modified by other code, so no need to copy. */
if (m->setImageId)
{
vrc = VDSetUuid(hdd, 0, m->imageId);
ComAssertRCThrow(vrc, E_FAIL);
}
if (m->setParentId)
{
vrc = VDSetParentUuid(hdd, 0, m->parentId);
ComAssertRCThrow(vrc, E_FAIL);
}
/* zap the information, these are no long-term members */
m->setImageId = false;
unconst(m->imageId).clear();
m->setParentId = false;
unconst(m->parentId).clear();
/* check the UUID */
RTUUID uuid;
vrc = VDGetUuid(hdd, 0, &uuid);
ComAssertRCThrow(vrc, E_FAIL);
if (isImport)
{
mediumId = uuid;
if (mediumId.isEmpty() && (m->hddOpenMode == OpenReadOnly))
// only when importing a VDMK that has no UUID, create one in memory
mediumId.create();
}
else
{
Assert(!mediumId.isEmpty());
if (mediumId != uuid)
{
lastAccessError = Utf8StrFmt(
tr("UUID {%RTuuid} of the medium '%s' does not match the value {%RTuuid} stored in the media registry ('%s')"),
&uuid,
location.c_str(),
mediumId.raw(),
m->pVirtualBox->settingsFilePath().c_str());
throw S_OK;
}
}
}
else
{
/* the backend does not support storing UUIDs within the
* underlying storage so use what we store in XML */
/* generate an UUID for an imported UUID-less medium */
if (isImport)
{
if (m->setImageId)
mediumId = m->imageId;
else
mediumId.create();
}
}
/* check the type */
unsigned uImageFlags;
vrc = VDGetImageFlags(hdd, 0, &uImageFlags);
ComAssertRCThrow(vrc, E_FAIL);
if (uImageFlags & VD_IMAGE_FLAGS_DIFF)
{
RTUUID parentId;
vrc = VDGetParentUuid(hdd, 0, &parentId);
ComAssertRCThrow(vrc, E_FAIL);
if (isImport)
{
/* the parent must be known to us. Note that we freely
* call locking methods of mVirtualBox and parent from the
* write lock (breaking the {parent,child} lock order)
* because there may be no concurrent access to the just
* opened hard disk on ther threads yet (and init() will
* fail if this method reporst MediumState_Inaccessible) */
Guid id = parentId;
ComObjPtr<Medium> pParent;
rc = m->pVirtualBox->findHardDisk(&id, NULL,
false /* aSetError */,
&pParent);
if (FAILED(rc))
{
lastAccessError = Utf8StrFmt(
tr("Parent hard disk with UUID {%RTuuid} of the hard disk '%s' is not found in the media registry ('%s')"),
&parentId, location.c_str(),
m->pVirtualBox->settingsFilePath().c_str());
throw S_OK;
}
/* we set mParent & children() */
AutoWriteLock treeLock(m->pVirtualBox->getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS);
Assert(m->pParent.isNull());
m->pParent = pParent;
m->pParent->m->llChildren.push_back(this);
}
else
{
/* we access mParent */
AutoReadLock treeLock(m->pVirtualBox->getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS);
/* check that parent UUIDs match. Note that there's no need
* for the parent's AutoCaller (our lifetime is bound to
* it) */
if (m->pParent.isNull())
{
lastAccessError = Utf8StrFmt(
tr("Hard disk '%s' is differencing but it is not associated with any parent hard disk in the media registry ('%s')"),
location.c_str(),
m->pVirtualBox->settingsFilePath().c_str());
throw S_OK;
}
AutoReadLock parentLock(m->pParent COMMA_LOCKVAL_SRC_POS);
if ( m->pParent->getState() != MediumState_Inaccessible
&& m->pParent->getId() != parentId)
{
lastAccessError = Utf8StrFmt(
tr("Parent UUID {%RTuuid} of the hard disk '%s' does not match UUID {%RTuuid} of its parent hard disk stored in the media registry ('%s')"),
&parentId, location.c_str(),
m->pParent->getId().raw(),
m->pVirtualBox->settingsFilePath().c_str());
throw S_OK;
}
/// @todo NEWMEDIA what to do if the parent is not
/// accessible while the diff is? Probably nothing. The
/// real code will detect the mismatch anyway.
}
}
mediumSize = VDGetFileSize(hdd, 0);
mediumLogicalSize = VDGetSize(hdd, 0) / _1M;
success = true;
}
catch (HRESULT aRC)
{
rc = aRC;
}
VDDestroy(hdd);
}
catch (HRESULT aRC)
{
rc = aRC;
}
alock.enter();
if (isImport)
unconst(m->id) = mediumId;
if (success)
{
m->size = mediumSize;
m->logicalSize = mediumLogicalSize;
m->strLastAccessError.setNull();
}
else
{
m->strLastAccessError = lastAccessError;
LogWarningFunc(("'%s' is not accessible (error='%s', rc=%Rhrc, vrc=%Rrc)\n",
location.c_str(), m->strLastAccessError.c_str(),
rc, vrc));
}
/* inform other callers if there are any */
RTSemEventMultiSignal(m->queryInfoSem);
m->queryInfoRunning = false;
/* Set the proper state according to the result of the check */
if (success)
m->preLockState = MediumState_Created;
else
m->preLockState = MediumState_Inaccessible;
if (flags & VD_OPEN_FLAGS_READONLY)
rc = UnlockRead(NULL);
else
rc = UnlockWrite(NULL);
if (FAILED(rc)) return rc;
return rc;
}
/**
* Sets the extended error info according to the current media state.
*
* @note Must be called from under this object's write or read lock.
*/
HRESULT Medium::setStateError()
{
HRESULT rc = E_FAIL;
switch (m->state)
{
case MediumState_NotCreated:
{
rc = setError(VBOX_E_INVALID_OBJECT_STATE,
tr("Storage for the medium '%s' is not created"),
m->strLocationFull.raw());
break;
}
case MediumState_Created:
{
rc = setError(VBOX_E_INVALID_OBJECT_STATE,
tr("Storage for the medium '%s' is already created"),
m->strLocationFull.raw());
break;
}
case MediumState_LockedRead:
{
rc = setError(VBOX_E_INVALID_OBJECT_STATE,
tr("Medium '%s' is locked for reading by another task"),
m->strLocationFull.raw());
break;
}
case MediumState_LockedWrite:
{
rc = setError(VBOX_E_INVALID_OBJECT_STATE,
tr("Medium '%s' is locked for writing by another task"),
m->strLocationFull.raw());
break;
}
case MediumState_Inaccessible:
{
/* be in sync with Console::powerUpThread() */
if (!m->strLastAccessError.isEmpty())
rc = setError(VBOX_E_INVALID_OBJECT_STATE,
tr("Medium '%s' is not accessible. %s"),
m->strLocationFull.raw(), m->strLastAccessError.c_str());
else
rc = setError(VBOX_E_INVALID_OBJECT_STATE,
tr("Medium '%s' is not accessible"),
m->strLocationFull.raw());
break;
}
case MediumState_Creating:
{
rc = setError(VBOX_E_INVALID_OBJECT_STATE,
tr("Storage for the medium '%s' is being created"),
m->strLocationFull.raw());
break;
}
case MediumState_Deleting:
{
rc = setError(VBOX_E_INVALID_OBJECT_STATE,
tr("Storage for the medium '%s' is being deleted"),
m->strLocationFull.raw());
break;
}
default:
{
AssertFailed();
break;
}
}
return rc;
}
/**
* Deletes the hard disk storage unit.
*
* If @a aProgress is not NULL but the object it points to is @c null then a new
* progress object will be created and assigned to @a *aProgress on success,
* otherwise the existing progress object is used. If Progress is NULL, then no
* progress object is created/used at all.
*
* When @a aWait is @c false, this method will create a thread to perform the
* delete operation asynchronously and will return immediately. Otherwise, it
* will perform the operation on the calling thread and will not return to the
* caller until the operation is completed. Note that @a aProgress cannot be
* NULL when @a aWait is @c false (this method will assert in this case).
*
* @param aProgress Where to find/store a Progress object to track operation
* completion.
* @param aWait @c true if this method should block instead of creating
* an asynchronous thread.
* @param pfNeedsSaveSettings Optional pointer to a bool that must have been initialized to false and that will be set to true
* by this function if the caller should invoke VirtualBox::saveSettings() because the global settings have changed.
* This only works in "wait" mode; otherwise saveSettings gets called automatically by the thread that was created,
* and this parameter is ignored.
*
* @note Locks mVirtualBox and this object for writing. Locks medium tree for
* writing.
*/
HRESULT Medium::deleteStorage(ComObjPtr<Progress> *aProgress,
bool aWait,
bool *pfNeedsSaveSettings)
{
AssertReturn(aProgress != NULL || aWait == true, E_FAIL);
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
HRESULT rc = S_OK;
ComObjPtr<Progress> pProgress;
Medium::Task *pTask = NULL;
try
{
/* we're accessing the media tree, and canClose() needs it too */
AutoMultiWriteLock2 multilock(&m->pVirtualBox->getMediaTreeLockHandle(),
this->lockHandle()
COMMA_LOCKVAL_SRC_POS);
LogFlowThisFunc(("aWait=%RTbool locationFull=%s\n", aWait, getLocationFull().c_str() ));
if ( !(m->formatObj->capabilities() & ( MediumFormatCapabilities_CreateDynamic
| MediumFormatCapabilities_CreateFixed)))
throw setError(VBOX_E_NOT_SUPPORTED,
tr("Hard disk format '%s' does not support storage deletion"),
m->strFormat.raw());
/* Note that we are fine with Inaccessible state too: a) for symmetry
* with create calls and b) because it doesn't really harm to try, if
* it is really inaccessible, the delete operation will fail anyway.
* Accepting Inaccessible state is especially important because all
* registered hard disks are initially Inaccessible upon VBoxSVC
* startup until COMGETTER(RefreshState) is called. Accept Deleting
* state because some callers need to put the image in this state early
* to prevent races. */
switch (m->state)
{
case MediumState_Created:
case MediumState_Deleting:
case MediumState_Inaccessible:
break;
default:
throw setStateError();
}
if (m->backRefs.size() != 0)
{
Utf8Str strMachines;
for (BackRefList::const_iterator it = m->backRefs.begin();
it != m->backRefs.end();
++it)
{
const BackRef &b = *it;
if (strMachines.length())
strMachines.append(", ");
strMachines.append(b.machineId.toString().c_str());
}
#ifdef DEBUG
dumpBackRefs();
#endif
throw setError(VBOX_E_OBJECT_IN_USE,
tr("Cannot delete storage: hard disk '%s' is still attached to the following %d virtual machine(s): %s"),
m->strLocationFull.c_str(),
m->backRefs.size(),
strMachines.c_str());
}
rc = canClose();
if (FAILED(rc))
throw rc;
/* go to Deleting state, so that the medium is not actually locked */
if (m->state != MediumState_Deleting)
{
rc = markForDeletion();
if (FAILED(rc))
throw rc;
}
/* Build the medium lock list. */
MediumLockList *pMediumLockList(new MediumLockList());
rc = createMediumLockList(true /* fFailIfInaccessible */,
true /* fMediumLockWrite */,
NULL,
*pMediumLockList);
if (FAILED(rc))
{
delete pMediumLockList;
throw rc;
}
rc = pMediumLockList->Lock();
if (FAILED(rc))
{
delete pMediumLockList;
throw setError(rc,
tr("Failed to lock media when deleting '%s'"),
getLocationFull().raw());
}
/* try to remove from the list of known hard disks before performing
* actual deletion (we favor the consistency of the media registry
* which would have been broken if unregisterWithVirtualBox() failed
* after we successfully deleted the storage) */
rc = unregisterWithVirtualBox(pfNeedsSaveSettings);
if (FAILED(rc))
throw rc;
// no longer need lock
multilock.release();
if (aProgress != NULL)
{
/* use the existing progress object... */
pProgress = *aProgress;
/* ...but create a new one if it is null */
if (pProgress.isNull())
{
pProgress.createObject();
rc = pProgress->init(m->pVirtualBox,
static_cast<IMedium*>(this),
BstrFmt(tr("Deleting hard disk storage unit '%s'"), m->strLocationFull.raw()),
FALSE /* aCancelable */);
if (FAILED(rc))
throw rc;
}
}
/* setup task object to carry out the operation sync/async */
pTask = new Medium::DeleteTask(this, pProgress, pMediumLockList);
rc = pTask->rc();
AssertComRC(rc);
if (FAILED(rc))
throw rc;
}
catch (HRESULT aRC) { rc = aRC; }
if (SUCCEEDED(rc))
{
if (aWait)
rc = runNow(pTask, NULL /* pfNeedsSaveSettings*/);
else
rc = startThread(pTask);
if (SUCCEEDED(rc) && aProgress != NULL)
*aProgress = pProgress;
}
else
{
if (pTask)
delete pTask;
/* Undo deleting state if necessary. */
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
unmarkForDeletion();
}
return rc;
}
/**
* Mark a medium for deletion.
*
* @note Caller must hold the write lock on this medium!
*/
HRESULT Medium::markForDeletion()
{
ComAssertRet(this->lockHandle()->isWriteLockOnCurrentThread(), E_FAIL);
switch (m->state)
{
case MediumState_Created:
case MediumState_Inaccessible:
m->preLockState = m->state;
m->state = MediumState_Deleting;
return S_OK;
default:
return setStateError();
}
}
/**
* Removes the "mark for deletion".
*
* @note Caller must hold the write lock on this medium!
*/
HRESULT Medium::unmarkForDeletion()
{
ComAssertRet(this->lockHandle()->isWriteLockOnCurrentThread(), E_FAIL);
switch (m->state)
{
case MediumState_Deleting:
m->state = m->preLockState;
return S_OK;
default:
return setStateError();
}
}
/**
* Mark a medium for deletion which is in locked state.
*
* @note Caller must hold the write lock on this medium!
*/
HRESULT Medium::markLockedForDeletion()
{
ComAssertRet(this->lockHandle()->isWriteLockOnCurrentThread(), E_FAIL);
if ( ( m->state == MediumState_LockedRead
|| m->state == MediumState_LockedWrite)
&& m->preLockState == MediumState_Created)
{
m->preLockState = MediumState_Deleting;
return S_OK;
}
else
return setStateError();
}
/**
* Removes the "mark for deletion" for a medium in locked state.
*
* @note Caller must hold the write lock on this medium!
*/
HRESULT Medium::unmarkLockedForDeletion()
{
ComAssertRet(this->lockHandle()->isWriteLockOnCurrentThread(), E_FAIL);
if ( ( m->state == MediumState_LockedRead
|| m->state == MediumState_LockedWrite)
&& m->preLockState == MediumState_Deleting)
{
m->preLockState = MediumState_Created;
return S_OK;
}
else
return setStateError();
}
/**
* Creates a new differencing storage unit using the given target hard disk's
* format and the location. Note that @c aTarget must be NotCreated.
*
* The @a aMediumLockList parameter contains the associated medium lock list,
* which must be in locked state. If @a aWait is @c true then the caller is
* responsible for unlocking.
*
* If @a aProgress is not NULL but the object it points to is @c null then a
* new progress object will be created and assigned to @a *aProgress on
* success, otherwise the existing progress object is used. If @a aProgress is
* NULL, then no progress object is created/used at all.
*
* When @a aWait is @c false, this method will create a thread to perform the
* create operation asynchronously and will return immediately. Otherwise, it
* will perform the operation on the calling thread and will not return to the
* caller until the operation is completed. Note that @a aProgress cannot be
* NULL when @a aWait is @c false (this method will assert in this case).
*
* @param aTarget Target hard disk.
* @param aVariant Precise image variant to create.
* @param aMediumLockList List of media which should be locked.
* @param aProgress Where to find/store a Progress object to track
* operation completion.
* @param aWait @c true if this method should block instead of
* creating an asynchronous thread.
* @param pfNeedsSaveSettings Optional pointer to a bool that must have been
* initialized to false and that will be set to true
* by this function if the caller should invoke
* VirtualBox::saveSettings() because the global
* settings have changed. This only works in "wait"
* mode; otherwise saveSettings is called
* automatically by the thread that was created,
* and this parameter is ignored.
*
* @note Locks this object and @a aTarget for writing.
*/
HRESULT Medium::createDiffStorage(ComObjPtr<Medium> &aTarget,
MediumVariant_T aVariant,
MediumLockList *aMediumLockList,
ComObjPtr<Progress> *aProgress,
bool aWait,
bool *pfNeedsSaveSettings)
{
AssertReturn(!aTarget.isNull(), E_FAIL);
AssertReturn(aMediumLockList, E_FAIL);
AssertReturn(aProgress != NULL || aWait == true, E_FAIL);
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
AutoCaller targetCaller(aTarget);
if (FAILED(targetCaller.rc())) return targetCaller.rc();
HRESULT rc = S_OK;
ComObjPtr<Progress> pProgress;
Medium::Task *pTask = NULL;
try
{
AutoMultiWriteLock2 alock(this, aTarget COMMA_LOCKVAL_SRC_POS);
ComAssertThrow(m->type != MediumType_Writethrough, E_FAIL);
ComAssertThrow(m->state == MediumState_LockedRead, E_FAIL);
if (aTarget->m->state != MediumState_NotCreated)
throw aTarget->setStateError();
/* Check that the hard disk is not attached to the current state of
* any VM referring to it. */
for (BackRefList::const_iterator it = m->backRefs.begin();
it != m->backRefs.end();
++it)
{
if (it->fInCurState)
{
/* Note: when a VM snapshot is being taken, all normal hard
* disks attached to the VM in the current state will be, as an
* exception, also associated with the snapshot which is about
* to create (see SnapshotMachine::init()) before deassociating
* them from the current state (which takes place only on
* success in Machine::fixupHardDisks()), so that the size of
* snapshotIds will be 1 in this case. The extra condition is
* used to filter out this legal situation. */
if (it->llSnapshotIds.size() == 0)
throw setError(VBOX_E_INVALID_OBJECT_STATE,
tr("Hard disk '%s' is attached to a virtual machine with UUID {%RTuuid}. No differencing hard disks based on it may be created until it is detached"),
m->strLocationFull.raw(), it->machineId.raw());
Assert(it->llSnapshotIds.size() == 1);
}
}
if (aProgress != NULL)
{
/* use the existing progress object... */
pProgress = *aProgress;
/* ...but create a new one if it is null */
if (pProgress.isNull())
{
pProgress.createObject();
rc = pProgress->init(m->pVirtualBox,
static_cast<IMedium*>(this),
BstrFmt(tr("Creating differencing hard disk storage unit '%s'"), aTarget->m->strLocationFull.raw()),
TRUE /* aCancelable */);
if (FAILED(rc))
throw rc;
}
}
/* setup task object to carry out the operation sync/async */
pTask = new Medium::CreateDiffTask(this, pProgress, aTarget, aVariant,
aMediumLockList,
aWait /* fKeepMediumLockList */);
rc = pTask->rc();
AssertComRC(rc);
if (FAILED(rc))
throw rc;
/* register a task (it will deregister itself when done) */
++m->numCreateDiffTasks;
Assert(m->numCreateDiffTasks != 0); /* overflow? */
aTarget->m->state = MediumState_Creating;
}
catch (HRESULT aRC) { rc = aRC; }
if (SUCCEEDED(rc))
{
if (aWait)
rc = runNow(pTask, pfNeedsSaveSettings);
else
rc = startThread(pTask);
if (SUCCEEDED(rc) && aProgress != NULL)
*aProgress = pProgress;
}
else if (pTask != NULL)
delete pTask;
return rc;
}
/**
* Prepares this (source) hard disk, target hard disk and all intermediate hard
* disks for the merge operation.
*
* This method is to be called prior to calling the #mergeTo() to perform
* necessary consistency checks and place involved hard disks to appropriate
* states. If #mergeTo() is not called or fails, the state modifications
* performed by this method must be undone by #cancelMergeTo().
*
* See #mergeTo() for more information about merging.
*
* @param pTarget Target hard disk.
* @param aMachineId Allowed machine attachment. NULL means do not check.
* @param aSnapshotId Allowed snapshot attachment. NULL or empty UUID means
* do not check.
* @param fLockMedia Flag whether to lock the medium lock list or not.
* If set to false and the medium lock list locking fails
* later you must call #cancelMergeTo().
* @param fMergeForward Resulting merge direction (out).
* @param pParentForTarget New parent for target medium after merge (out).
* @param aChildrenToReparent List of children of the source which will have
* to be reparented to the target after merge (out).
* @param aMediumLockList Medium locking information (out).
*
* @note Locks medium tree for reading. Locks this object, aTarget and all
* intermediate hard disks for writing.
*/
HRESULT Medium::prepareMergeTo(const ComObjPtr<Medium> &pTarget,
const Guid *aMachineId,
const Guid *aSnapshotId,
bool fLockMedia,
bool &fMergeForward,
ComObjPtr<Medium> &pParentForTarget,
MediaList &aChildrenToReparent,
MediumLockList * &aMediumLockList)
{
AssertReturn(pTarget != NULL, E_FAIL);
AssertReturn(pTarget != this, E_FAIL);
AutoCaller autoCaller(this);
AssertComRCReturnRC(autoCaller.rc());
AutoCaller targetCaller(pTarget);
AssertComRCReturnRC(targetCaller.rc());
HRESULT rc = S_OK;
fMergeForward = false;
pParentForTarget.setNull();
aChildrenToReparent.clear();
Assert(aMediumLockList == NULL);
aMediumLockList = NULL;
try
{
// locking: we need the tree lock first because we access parent pointers
AutoReadLock treeLock(m->pVirtualBox->getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS);
/* more sanity checking and figuring out the merge direction */
ComObjPtr<Medium> pMedium = getParent();
while (!pMedium.isNull() && pMedium != pTarget)
pMedium = pMedium->getParent();
if (pMedium == pTarget)
fMergeForward = false;
else
{
pMedium = pTarget->getParent();
while (!pMedium.isNull() && pMedium != this)
pMedium = pMedium->getParent();
if (pMedium == this)
fMergeForward = true;
else
{
Utf8Str tgtLoc;
{
AutoReadLock alock(pTarget COMMA_LOCKVAL_SRC_POS);
tgtLoc = pTarget->getLocationFull();
}
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
throw setError(E_FAIL,
tr("Hard disks '%s' and '%s' are unrelated"),
m->strLocationFull.raw(), tgtLoc.raw());
}
}
/* Build the lock list. */
aMediumLockList = new MediumLockList();
if (fMergeForward)
rc = pTarget->createMediumLockList(true /* fFailIfInaccessible */,
true /* fMediumLockWrite */,
NULL,
*aMediumLockList);
else
rc = createMediumLockList(true /* fFailIfInaccessible */,
false /* fMediumLockWrite */,
NULL,
*aMediumLockList);
if (FAILED(rc))
throw rc;
/* Sanity checking, must be after lock list creation as it depends on
* valid medium states. The medium objects must be accessible. Only
* do this if immediate locking is requested, otherwise it fails when
* we construct a medium lock list for an already running VM. Snapshot
* deletion uses this to simplify its life. */
if (fLockMedia)
{
{
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
if (m->state != MediumState_Created)
throw setStateError();
}
{
AutoReadLock alock(pTarget COMMA_LOCKVAL_SRC_POS);
if (pTarget->m->state != MediumState_Created)
throw pTarget->setStateError();
}
}
/* check medium attachment and other sanity conditions */
if (fMergeForward)
{
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
if (getChildren().size() > 1)
{
throw setError(E_FAIL,
tr("Medium '%s' involved in the merge operation has more than one child medium (%d)"),
m->strLocationFull.raw(), getChildren().size());
}
/* One backreference is only allowed if the machine ID is not empty
* and it matches the machine the image is attached to (including
* the snapshot ID if not empty). */
if ( m->backRefs.size() != 0
&& ( !aMachineId
|| m->backRefs.size() != 1
|| aMachineId->isEmpty()
|| *getFirstMachineBackrefId() != *aMachineId
|| ( (!aSnapshotId || !aSnapshotId->isEmpty())
&& *getFirstMachineBackrefSnapshotId() != *aSnapshotId)))
throw setError(E_FAIL,
tr("Medium '%s' is attached to %d virtual machines"),
m->strLocationFull.raw(), m->backRefs.size());
if (m->type == MediumType_Immutable)
throw setError(E_FAIL,
tr("Medium '%s' is immutable"),
m->strLocationFull.raw());
}
else
{
AutoReadLock alock(pTarget COMMA_LOCKVAL_SRC_POS);
if (pTarget->getChildren().size() > 1)
{
throw setError(E_FAIL,
tr("Medium '%s' involved in the merge operation has more than one child medium (%d)"),
pTarget->m->strLocationFull.raw(),
pTarget->getChildren().size());
}
if (pTarget->m->type == MediumType_Immutable)
throw setError(E_FAIL,
tr("Medium '%s' is immutable"),
pTarget->m->strLocationFull.raw());
}
ComObjPtr<Medium> pLast(fMergeForward ? (Medium *)pTarget : this);
ComObjPtr<Medium> pLastIntermediate = pLast->getParent();
for (pLast = pLastIntermediate;
!pLast.isNull() && pLast != pTarget && pLast != this;
pLast = pLast->getParent())
{
AutoReadLock alock(pLast COMMA_LOCKVAL_SRC_POS);
if (pLast->getChildren().size() > 1)
{
throw setError(E_FAIL,
tr("Medium '%s' involved in the merge operation has more than one child medium (%d)"),
pLast->m->strLocationFull.raw(),
pLast->getChildren().size());
}
if (pLast->m->backRefs.size() != 0)
throw setError(E_FAIL,
tr("Medium '%s' is attached to %d virtual machines"),
pLast->m->strLocationFull.raw(),
pLast->m->backRefs.size());
}
/* Update medium states appropriately */
if (m->state == MediumState_Created)
{
rc = markForDeletion();
if (FAILED(rc))
throw rc;
}
else
{
if (fLockMedia)
throw setStateError();
else if ( m->state == MediumState_LockedWrite
|| m->state == MediumState_LockedRead)
{
/* Either mark it for deletiion in locked state or allow
* others to have done so. */
if (m->preLockState == MediumState_Created)
markLockedForDeletion();
else if (m->preLockState != MediumState_Deleting)
throw setStateError();
}
else
throw setStateError();
}
if (fMergeForward)
{
/* we will need parent to reparent target */
pParentForTarget = m->pParent;
}
else
{
/* we will need to reparent children of the source */
for (MediaList::const_iterator it = getChildren().begin();
it != getChildren().end();
++it)
{
pMedium = *it;
if (fLockMedia)
{
rc = pMedium->LockWrite(NULL);
if (FAILED(rc))
throw rc;
}
aChildrenToReparent.push_back(pMedium);
}
}
for (pLast = pLastIntermediate;
!pLast.isNull() && pLast != pTarget && pLast != this;
pLast = pLast->getParent())
{
AutoWriteLock alock(pLast COMMA_LOCKVAL_SRC_POS);
if (pLast->m->state == MediumState_Created)
{
rc = pLast->markForDeletion();
if (FAILED(rc))
throw rc;
}
else
throw pLast->setStateError();
}
/* Tweak the lock list in the backward merge case, as the target
* isn't marked to be locked for writing yet. */
if (!fMergeForward)
{
MediumLockList::Base::iterator lockListBegin =
aMediumLockList->GetBegin();
MediumLockList::Base::iterator lockListEnd =
aMediumLockList->GetEnd();
lockListEnd--;
for (MediumLockList::Base::iterator it = lockListBegin;
it != lockListEnd;
++it)
{
MediumLock &mediumLock = *it;
if (mediumLock.GetMedium() == pTarget)
{
HRESULT rc2 = mediumLock.UpdateLock(true);
AssertComRC(rc2);
break;
}
}
}
if (fLockMedia)
{
rc = aMediumLockList->Lock();
if (FAILED(rc))
{
AutoReadLock alock(pTarget COMMA_LOCKVAL_SRC_POS);
throw setError(rc,
tr("Failed to lock media when merging to '%s'"),
pTarget->getLocationFull().raw());
}
}
}
catch (HRESULT aRC) { rc = aRC; }
if (FAILED(rc))
{
delete aMediumLockList;
aMediumLockList = NULL;
}
return rc;
}
/**
* Merges this hard disk to the specified hard disk which must be either its
* direct ancestor or descendant.
*
* Given this hard disk is SOURCE and the specified hard disk is TARGET, we will
* get two varians of the merge operation:
*
* forward merge
* ------------------------->
* [Extra] <- SOURCE <- Intermediate <- TARGET
* Any Del Del LockWr
*
*
* backward merge
* <-------------------------
* TARGET <- Intermediate <- SOURCE <- [Extra]
* LockWr Del Del LockWr
*
* Each diagram shows the involved hard disks on the hard disk chain where
* SOURCE and TARGET belong. Under each hard disk there is a state value which
* the hard disk must have at a time of the mergeTo() call.
*
* The hard disks in the square braces may be absent (e.g. when the forward
* operation takes place and SOURCE is the base hard disk, or when the backward
* merge operation takes place and TARGET is the last child in the chain) but if
* they present they are involved too as shown.
*
* Nor the source hard disk neither intermediate hard disks may be attached to
* any VM directly or in the snapshot, otherwise this method will assert.
*
* The #prepareMergeTo() method must be called prior to this method to place all
* involved to necessary states and perform other consistency checks.
*
* If @a aWait is @c true then this method will perform the operation on the
* calling thread and will not return to the caller until the operation is
* completed. When this method succeeds, all intermediate hard disk objects in
* the chain will be uninitialized, the state of the target hard disk (and all
* involved extra hard disks) will be restored. @a aMediumLockList will not be
* deleted, whether the operation is successful or not. The caller has to do
* this if appropriate. Note that this (source) hard disk is not uninitialized
* because of possible AutoCaller instances held by the caller of this method
* on the current thread. It's therefore the responsibility of the caller to
* call Medium::uninit() after releasing all callers.
*
* If @a aWait is @c false then this method will create a thread to perform the
* operation asynchronously and will return immediately. If the operation
* succeeds, the thread will uninitialize the source hard disk object and all
* intermediate hard disk objects in the chain, reset the state of the target
* hard disk (and all involved extra hard disks) and delete @a aMediumLockList.
* If the operation fails, the thread will only reset the states of all
* involved hard disks and delete @a aMediumLockList.
*
* When this method fails (regardless of the @a aWait mode), it is a caller's
* responsiblity to undo state changes and delete @a aMediumLockList using
* #cancelMergeTo().
*
* If @a aProgress is not NULL but the object it points to is @c null then a new
* progress object will be created and assigned to @a *aProgress on success,
* otherwise the existing progress object is used. If Progress is NULL, then no
* progress object is created/used at all. Note that @a aProgress cannot be
* NULL when @a aWait is @c false (this method will assert in this case).
*
* @param pTarget Target hard disk.
* @param fMergeForward Merge direction.
* @param pParentForTarget New parent for target medium after merge.
* @param aChildrenToReparent List of children of the source which will have
* to be reparented to the target after merge.
* @param aMediumLockList Medium locking information.
* @param aProgress Where to find/store a Progress object to track operation
* completion.
* @param aWait @c true if this method should block instead of creating
* an asynchronous thread.
* @param pfNeedsSaveSettings Optional pointer to a bool that must have been initialized to false and that will be set to true
* by this function if the caller should invoke VirtualBox::saveSettings() because the global settings have changed.
* This only works in "wait" mode; otherwise saveSettings gets called automatically by the thread that was created,
* and this parameter is ignored.
*
* @note Locks the tree lock for writing. Locks the hard disks from the chain
* for writing.
*/
HRESULT Medium::mergeTo(const ComObjPtr<Medium> &pTarget,
bool fMergeForward,
const ComObjPtr<Medium> &pParentForTarget,
const MediaList &aChildrenToReparent,
MediumLockList *aMediumLockList,
ComObjPtr <Progress> *aProgress,
bool aWait,
bool *pfNeedsSaveSettings)
{
AssertReturn(pTarget != NULL, E_FAIL);
AssertReturn(pTarget != this, E_FAIL);
AssertReturn(aMediumLockList != NULL, E_FAIL);
AssertReturn(aProgress != NULL || aWait == true, E_FAIL);
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
AutoCaller targetCaller(pTarget);
AssertComRCReturnRC(targetCaller.rc());
HRESULT rc = S_OK;
ComObjPtr <Progress> pProgress;
Medium::Task *pTask = NULL;
try
{
if (aProgress != NULL)
{
/* use the existing progress object... */
pProgress = *aProgress;
/* ...but create a new one if it is null */
if (pProgress.isNull())
{
Utf8Str tgtName;
{
AutoReadLock alock(pTarget COMMA_LOCKVAL_SRC_POS);
tgtName = pTarget->getName();
}
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
pProgress.createObject();
rc = pProgress->init(m->pVirtualBox,
static_cast<IMedium*>(this),
BstrFmt(tr("Merging hard disk '%s' to '%s'"),
getName().raw(),
tgtName.raw()),
TRUE /* aCancelable */);
if (FAILED(rc))
throw rc;
}
}
/* setup task object to carry out the operation sync/async */
pTask = new Medium::MergeTask(this, pTarget, fMergeForward,
pParentForTarget, aChildrenToReparent,
pProgress, aMediumLockList,
aWait /* fKeepMediumLockList */);
rc = pTask->rc();
AssertComRC(rc);
if (FAILED(rc))
throw rc;
}
catch (HRESULT aRC) { rc = aRC; }
if (SUCCEEDED(rc))
{
if (aWait)
rc = runNow(pTask, pfNeedsSaveSettings);
else
rc = startThread(pTask);
if (SUCCEEDED(rc) && aProgress != NULL)
*aProgress = pProgress;
}
else if (pTask != NULL)
delete pTask;
return rc;
}
/**
* Undoes what #prepareMergeTo() did. Must be called if #mergeTo() is not
* called or fails. Frees memory occupied by @a aMediumLockList and unlocks
* the medium objects in @a aChildrenToReparent.
*
* @param aChildrenToReparent List of children of the source which will have
* to be reparented to the target after merge.
* @param aMediumLockList Medium locking information.
*
* @note Locks the hard disks from the chain for writing.
*/
void Medium::cancelMergeTo(const MediaList &aChildrenToReparent,
MediumLockList *aMediumLockList)
{
AutoCaller autoCaller(this);
AssertComRCReturnVoid(autoCaller.rc());
AssertReturnVoid(aMediumLockList != NULL);
/* Revert media marked for deletion to previous state. */
HRESULT rc;
MediumLockList::Base::const_iterator mediumListBegin =
aMediumLockList->GetBegin();
MediumLockList::Base::const_iterator mediumListEnd =
aMediumLockList->GetEnd();
for (MediumLockList::Base::const_iterator it = mediumListBegin;
it != mediumListEnd;
++it)
{
const MediumLock &mediumLock = *it;
const ComObjPtr<Medium> &pMedium = mediumLock.GetMedium();
AutoWriteLock alock(pMedium COMMA_LOCKVAL_SRC_POS);
if (pMedium->m->state == MediumState_Deleting)
{
rc = pMedium->unmarkForDeletion();
AssertComRC(rc);
}
}
/* the destructor will do the work */
delete aMediumLockList;
/* unlock the children which had to be reparented */
for (MediaList::const_iterator it = aChildrenToReparent.begin();
it != aChildrenToReparent.end();
++it)
{
const ComObjPtr<Medium> &pMedium = *it;
AutoWriteLock alock(pMedium COMMA_LOCKVAL_SRC_POS);
pMedium->UnlockWrite(NULL);
}
}
/**
* Checks that the format ID is valid and sets it on success.
*
* Note that this method will caller-reference the format object on success!
* This reference must be released somewhere to let the MediumFormat object be
* uninitialized.
*
* @note Must be called from under this object's write lock.
*/
HRESULT Medium::setFormat(CBSTR aFormat)
{
/* get the format object first */
{
AutoReadLock propsLock(m->pVirtualBox->systemProperties() COMMA_LOCKVAL_SRC_POS);
unconst(m->formatObj)
= m->pVirtualBox->systemProperties()->mediumFormat(aFormat);
if (m->formatObj.isNull())
return setError(E_INVALIDARG,
tr("Invalid hard disk storage format '%ls'"),
aFormat);
/* reference the format permanently to prevent its unexpected
* uninitialization */
HRESULT rc = m->formatObj->addCaller();
AssertComRCReturnRC(rc);
/* get properties (preinsert them as keys in the map). Note that the
* map doesn't grow over the object life time since the set of
* properties is meant to be constant. */
Assert(m->properties.empty());
for (MediumFormat::PropertyList::const_iterator it =
m->formatObj->properties().begin();
it != m->formatObj->properties().end();
++it)
{
m->properties.insert(std::make_pair(it->name, Bstr::Null));
}
}
unconst(m->strFormat) = aFormat;
return S_OK;
}
/**
* @note Also reused by Medium::Reset().
*
* @note Caller must hold the media tree write lock!
*/
HRESULT Medium::canClose()
{
Assert(m->pVirtualBox->getMediaTreeLockHandle().isWriteLockOnCurrentThread());
if (getChildren().size() != 0)
return setError(E_FAIL,
tr("Cannot close medium '%s' because it has %d child hard disk(s)"),
m->strLocationFull.raw(), getChildren().size());
return S_OK;
}
/**
* Calls either VirtualBox::unregisterImage or VirtualBox::unregisterHardDisk depending
* on the device type of this medium.
*
* @param pfNeedsSaveSettings Optional pointer to a bool that must have been initialized to false and that will be set to true
* by this function if the caller should invoke VirtualBox::saveSettings() because the global settings have changed.
*
* @note Caller must have locked the media tree lock for writing!
*/
HRESULT Medium::unregisterWithVirtualBox(bool *pfNeedsSaveSettings)
{
/* Note that we need to de-associate ourselves from the parent to let
* unregisterHardDisk() properly save the registry */
/* we modify mParent and access children */
Assert(m->pVirtualBox->getMediaTreeLockHandle().isWriteLockOnCurrentThread());
Medium *pParentBackup = m->pParent;
AssertReturn(getChildren().size() == 0, E_FAIL);
if (m->pParent)
deparent();
HRESULT rc = E_FAIL;
switch (m->devType)
{
case DeviceType_DVD:
rc = m->pVirtualBox->unregisterImage(this, DeviceType_DVD, pfNeedsSaveSettings);
break;
case DeviceType_Floppy:
rc = m->pVirtualBox->unregisterImage(this, DeviceType_Floppy, pfNeedsSaveSettings);
break;
case DeviceType_HardDisk:
rc = m->pVirtualBox->unregisterHardDisk(this, pfNeedsSaveSettings);
break;
default:
break;
}
if (FAILED(rc))
{
if (pParentBackup)
{
/* re-associate with the parent as we are still relatives in the
* registry */
m->pParent = pParentBackup;
m->pParent->m->llChildren.push_back(this);
}
}
return rc;
}
/**
* Returns the last error message collected by the vdErrorCall callback and
* resets it.
*
* The error message is returned prepended with a dot and a space, like this:
* <code>
* ". <error_text> (%Rrc)"
* </code>
* to make it easily appendable to a more general error message. The @c %Rrc
* format string is given @a aVRC as an argument.
*
* If there is no last error message collected by vdErrorCall or if it is a
* null or empty string, then this function returns the following text:
* <code>
* " (%Rrc)"
* </code>
*
* @note Doesn't do any object locking; it is assumed that the caller makes sure
* the callback isn't called by more than one thread at a time.
*
* @param aVRC VBox error code to use when no error message is provided.
*/
Utf8Str Medium::vdError(int aVRC)
{
Utf8Str error;
if (m->vdError.isEmpty())
error = Utf8StrFmt(" (%Rrc)", aVRC);
else
error = Utf8StrFmt(".\n%s", m->vdError.raw());
m->vdError.setNull();
return error;
}
/**
* Error message callback.
*
* Puts the reported error message to the m->vdError field.
*
* @note Doesn't do any object locking; it is assumed that the caller makes sure
* the callback isn't called by more than one thread at a time.
*
* @param pvUser The opaque data passed on container creation.
* @param rc The VBox error code.
* @param RT_SRC_POS_DECL Use RT_SRC_POS.
* @param pszFormat Error message format string.
* @param va Error message arguments.
*/
/*static*/
DECLCALLBACK(void) Medium::vdErrorCall(void *pvUser, int rc, RT_SRC_POS_DECL,
const char *pszFormat, va_list va)
{
NOREF(pszFile); NOREF(iLine); NOREF(pszFunction); /* RT_SRC_POS_DECL */
Medium *that = static_cast<Medium*>(pvUser);
AssertReturnVoid(that != NULL);
if (that->m->vdError.isEmpty())
that->m->vdError =
Utf8StrFmt("%s (%Rrc)", Utf8StrFmtVA(pszFormat, va).raw(), rc);
else
that->m->vdError =
Utf8StrFmt("%s.\n%s (%Rrc)", that->m->vdError.raw(),
Utf8StrFmtVA(pszFormat, va).raw(), rc);
}
/* static */
DECLCALLBACK(bool) Medium::vdConfigAreKeysValid(void *pvUser,
const char * /* pszzValid */)
{
Medium *that = static_cast<Medium*>(pvUser);
AssertReturn(that != NULL, false);
/* we always return true since the only keys we have are those found in
* VDBACKENDINFO */
return true;
}
/* static */
DECLCALLBACK(int) Medium::vdConfigQuerySize(void *pvUser, const char *pszName,
size_t *pcbValue)
{
AssertReturn(VALID_PTR(pcbValue), VERR_INVALID_POINTER);
Medium *that = static_cast<Medium*>(pvUser);
AssertReturn(that != NULL, VERR_GENERAL_FAILURE);
Data::PropertyMap::const_iterator it =
that->m->properties.find(Bstr(pszName));
if (it == that->m->properties.end())
return VERR_CFGM_VALUE_NOT_FOUND;
/* we interpret null values as "no value" in Medium */
if (it->second.isEmpty())
return VERR_CFGM_VALUE_NOT_FOUND;
*pcbValue = it->second.length() + 1 /* include terminator */;
return VINF_SUCCESS;
}
/* static */
DECLCALLBACK(int) Medium::vdConfigQuery(void *pvUser, const char *pszName,
char *pszValue, size_t cchValue)
{
AssertReturn(VALID_PTR(pszValue), VERR_INVALID_POINTER);
Medium *that = static_cast<Medium*>(pvUser);
AssertReturn(that != NULL, VERR_GENERAL_FAILURE);
Data::PropertyMap::const_iterator it =
that->m->properties.find(Bstr(pszName));
if (it == that->m->properties.end())
return VERR_CFGM_VALUE_NOT_FOUND;
Utf8Str value = it->second;
if (value.length() >= cchValue)
return VERR_CFGM_NOT_ENOUGH_SPACE;
/* we interpret null values as "no value" in Medium */
if (it->second.isEmpty())
return VERR_CFGM_VALUE_NOT_FOUND;
memcpy(pszValue, value.c_str(), value.length() + 1);
return VINF_SUCCESS;
}
/**
* Starts a new thread driven by the appropriate Medium::Task::handler() method.
*
* @note When the task is executed by this method, IProgress::notifyComplete()
* is automatically called for the progress object associated with this
* task when the task is finished to signal the operation completion for
* other threads asynchronously waiting for it.
*/
HRESULT Medium::startThread(Medium::Task *pTask)
{
#ifdef VBOX_WITH_MAIN_LOCK_VALIDATION
/* Extreme paranoia: The calling thread should not hold the medium
* tree lock or any medium lock. Since there is no separate lock class
* for medium objects be even more strict: no other object locks. */
Assert(!AutoLockHoldsLocksInClass(LOCKCLASS_LISTOFMEDIA));
Assert(!AutoLockHoldsLocksInClass(getLockingClass()));
#endif
/// @todo use a more descriptive task name
int vrc = RTThreadCreate(NULL, Medium::Task::fntMediumTask, pTask,
0, RTTHREADTYPE_MAIN_HEAVY_WORKER, 0,
"Medium::Task");
if (RT_FAILURE(vrc))
{
delete pTask;
ComAssertMsgRCRet(vrc,
("Could not create Medium::Task thread (%Rrc)\n",
vrc),
E_FAIL);
}
return S_OK;
}
/**
* Fix the parent UUID of all children to point to this medium as their
* parent.
*/
HRESULT Medium::fixParentUuidOfChildren(const MediaList &childrenToReparent)
{
MediumLockList mediumLockList;
HRESULT rc = createMediumLockList(true /* fFailIfInaccessible */,
false /* fMediumLockWrite */,
this,
mediumLockList);
AssertComRCReturnRC(rc);
try
{
PVBOXHDD hdd;
int vrc = VDCreate(m->vdDiskIfaces, &hdd);
ComAssertRCThrow(vrc, E_FAIL);
try
{
MediumLockList::Base::iterator lockListBegin =
mediumLockList.GetBegin();
MediumLockList::Base::iterator lockListEnd =
mediumLockList.GetEnd();
for (MediumLockList::Base::iterator it = lockListBegin;
it != lockListEnd;
++it)
{
MediumLock &mediumLock = *it;
const ComObjPtr<Medium> &pMedium = mediumLock.GetMedium();
AutoReadLock alock(pMedium COMMA_LOCKVAL_SRC_POS);
// open the image
vrc = VDOpen(hdd,
pMedium->m->strFormat.c_str(),
pMedium->m->strLocationFull.c_str(),
VD_OPEN_FLAGS_READONLY,
pMedium->m->vdDiskIfaces);
if (RT_FAILURE(vrc))
throw vrc;
}
for (MediaList::const_iterator it = childrenToReparent.begin();
it != childrenToReparent.end();
++it)
{
/* VD_OPEN_FLAGS_INFO since UUID is wrong yet */
vrc = VDOpen(hdd,
(*it)->m->strFormat.c_str(),
(*it)->m->strLocationFull.c_str(),
VD_OPEN_FLAGS_INFO,
(*it)->m->vdDiskIfaces);
if (RT_FAILURE(vrc))
throw vrc;
vrc = VDSetParentUuid(hdd, VD_LAST_IMAGE, m->id);
if (RT_FAILURE(vrc))
throw vrc;
vrc = VDClose(hdd, false /* fDelete */);
if (RT_FAILURE(vrc))
throw vrc;
(*it)->UnlockWrite(NULL);
}
}
catch (HRESULT aRC) { rc = aRC; }
catch (int aVRC)
{
throw setError(E_FAIL,
tr("Could not update medium UUID references to parent '%s' (%s)"),
m->strLocationFull.raw(),
vdError(aVRC).raw());
}
VDDestroy(hdd);
}
catch (HRESULT aRC) { rc = aRC; }
return rc;
}
/**
* Runs Medium::Task::handler() on the current thread instead of creating
* a new one.
*
* This call implies that it is made on another temporary thread created for
* some asynchronous task. Avoid calling it from a normal thread since the task
* operations are potentially lengthy and will block the calling thread in this
* case.
*
* @note When the task is executed by this method, IProgress::notifyComplete()
* is not called for the progress object associated with this task when
* the task is finished. Instead, the result of the operation is returned
* by this method directly and it's the caller's responsibility to
* complete the progress object in this case.
*/
HRESULT Medium::runNow(Medium::Task *pTask,
bool *pfNeedsSaveSettings)
{
#ifdef VBOX_WITH_MAIN_LOCK_VALIDATION
/* Extreme paranoia: The calling thread should not hold the medium
* tree lock or any medium lock. Since there is no separate lock class
* for medium objects be even more strict: no other object locks. */
Assert(!AutoLockHoldsLocksInClass(LOCKCLASS_LISTOFMEDIA));
Assert(!AutoLockHoldsLocksInClass(getLockingClass()));
#endif
pTask->m_pfNeedsSaveSettings = pfNeedsSaveSettings;
/* NIL_RTTHREAD indicates synchronous call. */
return (HRESULT)Medium::Task::fntMediumTask(NIL_RTTHREAD, pTask);
}
/**
* Implementation code for the "create base" task.
*
* This only gets started from Medium::CreateBaseStorage() and always runs
* asynchronously. As a result, we always save the VirtualBox.xml file when
* we're done here.
*
* @param task
* @return
*/
HRESULT Medium::taskCreateBaseHandler(Medium::CreateBaseTask &task)
{
HRESULT rc = S_OK;
/* these parameters we need after creation */
uint64_t size = 0, logicalSize = 0;
bool fGenerateUuid = false;
try
{
AutoWriteLock thisLock(this COMMA_LOCKVAL_SRC_POS);
/* The object may request a specific UUID (through a special form of
* the setLocation() argument). Otherwise we have to generate it */
Guid id = m->id;
fGenerateUuid = id.isEmpty();
if (fGenerateUuid)
{
id.create();
/* VirtualBox::registerHardDisk() will need UUID */
unconst(m->id) = id;
}
Utf8Str format(m->strFormat);
Utf8Str location(m->strLocationFull);
uint64_t capabilities = m->formatObj->capabilities();
ComAssertThrow(capabilities & ( VD_CAP_CREATE_FIXED
| VD_CAP_CREATE_DYNAMIC), E_FAIL);
Assert(m->state == MediumState_Creating);
PVBOXHDD hdd;
int vrc = VDCreate(m->vdDiskIfaces, &hdd);
ComAssertRCThrow(vrc, E_FAIL);
/* unlock before the potentially lengthy operation */
thisLock.release();
try
{
/* ensure the directory exists */
rc = VirtualBox::ensureFilePathExists(location);
if (FAILED(rc))
throw rc;
PDMMEDIAGEOMETRY geo = { 0, 0, 0 }; /* auto-detect */
vrc = VDCreateBase(hdd,
format.c_str(),
location.c_str(),
task.mSize * _1M,
task.mVariant,
NULL,
&geo,
&geo,
id.raw(),
VD_OPEN_FLAGS_NORMAL,
NULL,
task.mVDOperationIfaces);
if (RT_FAILURE(vrc))
{
throw setError(E_FAIL,
tr("Could not create the hard disk storage unit '%s'%s"),
location.raw(), vdError(vrc).raw());
}
size = VDGetFileSize(hdd, 0);
logicalSize = VDGetSize(hdd, 0) / _1M;
}
catch (HRESULT aRC) { rc = aRC; }
VDDestroy(hdd);
}
catch (HRESULT aRC) { rc = aRC; }
if (SUCCEEDED(rc))
{
/* register with mVirtualBox as the last step and move to
* Created state only on success (leaving an orphan file is
* better than breaking media registry consistency) */
bool fNeedsSaveSettings = false;
AutoWriteLock treeLock(m->pVirtualBox->getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS);
rc = m->pVirtualBox->registerHardDisk(this, &fNeedsSaveSettings);
treeLock.release();
if (fNeedsSaveSettings)
{
AutoWriteLock vboxlock(m->pVirtualBox COMMA_LOCKVAL_SRC_POS);
m->pVirtualBox->saveSettings();
}
}
// reenter the lock before changing state
AutoWriteLock thisLock(this COMMA_LOCKVAL_SRC_POS);
if (SUCCEEDED(rc))
{
m->state = MediumState_Created;
m->size = size;
m->logicalSize = logicalSize;
}
else
{
/* back to NotCreated on failure */
m->state = MediumState_NotCreated;
/* reset UUID to prevent it from being reused next time */
if (fGenerateUuid)
unconst(m->id).clear();
}
return rc;
}
/**
* Implementation code for the "create diff" task.
*
* This task always gets started from Medium::createDiffStorage() and can run
* synchronously or asynchronously depending on the "wait" parameter passed to
* that function. If we run synchronously, the caller expects the bool
* *pfNeedsSaveSettings to be set before returning; otherwise (in asynchronous
* mode), we save the settings ourselves.
*
* @param task
* @return
*/
HRESULT Medium::taskCreateDiffHandler(Medium::CreateDiffTask &task)
{
HRESULT rc = S_OK;
bool fNeedsSaveSettings = false;
const ComObjPtr<Medium> &pTarget = task.mTarget;
uint64_t size = 0, logicalSize = 0;
bool fGenerateUuid = false;
try
{
/* Lock both in {parent,child} order. */
AutoMultiWriteLock2 mediaLock(this, pTarget COMMA_LOCKVAL_SRC_POS);
/* The object may request a specific UUID (through a special form of
* the setLocation() argument). Otherwise we have to generate it */
Guid targetId = pTarget->m->id;
fGenerateUuid = targetId.isEmpty();
if (fGenerateUuid)
{
targetId.create();
/* VirtualBox::registerHardDisk() will need UUID */
unconst(pTarget->m->id) = targetId;
}
Guid id = m->id;
Utf8Str targetFormat(pTarget->m->strFormat);
Utf8Str targetLocation(pTarget->m->strLocationFull);
uint64_t capabilities = m->formatObj->capabilities();
ComAssertThrow(capabilities & VD_CAP_CREATE_DYNAMIC, E_FAIL);
Assert(pTarget->m->state == MediumState_Creating);
Assert(m->state == MediumState_LockedRead);
PVBOXHDD hdd;
int vrc = VDCreate(m->vdDiskIfaces, &hdd);
ComAssertRCThrow(vrc, E_FAIL);
/* the two media are now protected by their non-default states;
* unlock the media before the potentially lengthy operation */
mediaLock.release();
try
{
/* Open all hard disk images in the target chain but the last. */
MediumLockList::Base::const_iterator targetListBegin =
task.mpMediumLockList->GetBegin();
MediumLockList::Base::const_iterator targetListEnd =
task.mpMediumLockList->GetEnd();
for (MediumLockList::Base::const_iterator it = targetListBegin;
it != targetListEnd;
++it)
{
const MediumLock &mediumLock = *it;
const ComObjPtr<Medium> &pMedium = mediumLock.GetMedium();
AutoReadLock alock(pMedium COMMA_LOCKVAL_SRC_POS);
/* Skip over the target diff image */
if (pMedium->m->state == MediumState_Creating)
continue;
/* sanity check */
Assert(pMedium->m->state == MediumState_LockedRead);
/* Open all images in appropriate mode. */
vrc = VDOpen(hdd,
pMedium->m->strFormat.c_str(),
pMedium->m->strLocationFull.c_str(),
VD_OPEN_FLAGS_READONLY,
pMedium->m->vdDiskIfaces);
if (RT_FAILURE(vrc))
throw setError(E_FAIL,
tr("Could not open the hard disk storage unit '%s'%s"),
pMedium->m->strLocationFull.raw(),
vdError(vrc).raw());
}
/* ensure the target directory exists */
rc = VirtualBox::ensureFilePathExists(targetLocation);
if (FAILED(rc))
throw rc;
vrc = VDCreateDiff(hdd,
targetFormat.c_str(),
targetLocation.c_str(),
task.mVariant | VD_IMAGE_FLAGS_DIFF,
NULL,
targetId.raw(),
id.raw(),
VD_OPEN_FLAGS_NORMAL,
pTarget->m->vdDiskIfaces,
task.mVDOperationIfaces);
if (RT_FAILURE(vrc))
throw setError(E_FAIL,
tr("Could not create the differencing hard disk storage unit '%s'%s"),
targetLocation.raw(), vdError(vrc).raw());
size = VDGetFileSize(hdd, VD_LAST_IMAGE);
logicalSize = VDGetSize(hdd, VD_LAST_IMAGE) / _1M;
}
catch (HRESULT aRC) { rc = aRC; }
VDDestroy(hdd);
}
catch (HRESULT aRC) { rc = aRC; }
if (SUCCEEDED(rc))
{
AutoWriteLock treeLock(m->pVirtualBox->getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS);
Assert(pTarget->m->pParent.isNull());
/* associate the child with the parent */
pTarget->m->pParent = this;
m->llChildren.push_back(pTarget);
/** @todo r=klaus neither target nor base() are locked,
* potential race! */
/* diffs for immutable hard disks are auto-reset by default */
pTarget->m->autoReset = (getBase()->m->type == MediumType_Immutable);
/* register with mVirtualBox as the last step and move to
* Created state only on success (leaving an orphan file is
* better than breaking media registry consistency) */
rc = m->pVirtualBox->registerHardDisk(pTarget, &fNeedsSaveSettings);
if (FAILED(rc))
/* break the parent association on failure to register */
deparent();
}
AutoMultiWriteLock2 mediaLock(this, pTarget COMMA_LOCKVAL_SRC_POS);
if (SUCCEEDED(rc))
{
pTarget->m->state = MediumState_Created;
pTarget->m->size = size;
pTarget->m->logicalSize = logicalSize;
}
else
{
/* back to NotCreated on failure */
pTarget->m->state = MediumState_NotCreated;
pTarget->m->autoReset = false;
/* reset UUID to prevent it from being reused next time */
if (fGenerateUuid)
unconst(pTarget->m->id).clear();
}
if (task.isAsync())
{
if (fNeedsSaveSettings)
{
mediaLock.release();
AutoWriteLock vboxlock(m->pVirtualBox COMMA_LOCKVAL_SRC_POS);
m->pVirtualBox->saveSettings();
}
}
else
// synchronous mode: report save settings result to caller
if (task.m_pfNeedsSaveSettings)
*task.m_pfNeedsSaveSettings = fNeedsSaveSettings;
/* deregister the task registered in createDiffStorage() */
Assert(m->numCreateDiffTasks != 0);
--m->numCreateDiffTasks;
/* Note that in sync mode, it's the caller's responsibility to
* unlock the hard disk */
return rc;
}
/**
* Implementation code for the "merge" task.
*
* This task always gets started from Medium::mergeTo() and can run
* synchronously or asynchrously depending on the "wait" parameter passed to
* that function. If we run synchronously, the caller expects the bool
* *pfNeedsSaveSettings to be set before returning; otherwise (in asynchronous
* mode), we save the settings ourselves.
*
* @param task
* @return
*/
HRESULT Medium::taskMergeHandler(Medium::MergeTask &task)
{
HRESULT rc = S_OK;
const ComObjPtr<Medium> &pTarget = task.mTarget;
try
{
PVBOXHDD hdd;
int vrc = VDCreate(m->vdDiskIfaces, &hdd);
ComAssertRCThrow(vrc, E_FAIL);
try
{
// Similar code appears in SessionMachine::onlineMergeMedium, so
// if you make any changes below check whether they are applicable
// in that context as well.
unsigned uTargetIdx = VD_LAST_IMAGE;
unsigned uSourceIdx = VD_LAST_IMAGE;
/* Open all hard disks in the chain. */
MediumLockList::Base::iterator lockListBegin =
task.mpMediumLockList->GetBegin();
MediumLockList::Base::iterator lockListEnd =
task.mpMediumLockList->GetEnd();
unsigned i = 0;
for (MediumLockList::Base::iterator it = lockListBegin;
it != lockListEnd;
++it)
{
MediumLock &mediumLock = *it;
const ComObjPtr<Medium> &pMedium = mediumLock.GetMedium();
if (pMedium == this)
uSourceIdx = i;
else if (pMedium == pTarget)
uTargetIdx = i;
AutoReadLock alock(pMedium COMMA_LOCKVAL_SRC_POS);
/*
* complex sanity (sane complexity)
*
* The current image must be in the Deleting (image is merged)
* or LockedRead (parent image) state if it is not the target.
* If it is the target it must be in the LockedWrite state.
*/
Assert( ( pMedium != pTarget
&& ( pMedium->m->state == MediumState_Deleting
|| pMedium->m->state == MediumState_LockedRead))
|| ( pMedium == pTarget
&& pMedium->m->state == MediumState_LockedWrite));
/*
* Image must be the target, in the LockedRead state
* or Deleting state where it is not allowed to be attached
* to a virtual machine.
*/
Assert( pMedium == pTarget
|| pMedium->m->state == MediumState_LockedRead
|| ( pMedium->m->backRefs.size() == 0
&& pMedium->m->state == MediumState_Deleting));
/* The source medium must be in Deleting state. */
Assert( pMedium != this
|| pMedium->m->state == MediumState_Deleting);
unsigned uOpenFlags = 0;
if ( pMedium->m->state == MediumState_LockedRead
|| pMedium->m->state == MediumState_Deleting)
uOpenFlags = VD_OPEN_FLAGS_READONLY;
/* Open the image */
vrc = VDOpen(hdd,
pMedium->m->strFormat.c_str(),
pMedium->m->strLocationFull.c_str(),
uOpenFlags,
pMedium->m->vdDiskIfaces);
if (RT_FAILURE(vrc))
throw vrc;
i++;
}
ComAssertThrow( uSourceIdx != VD_LAST_IMAGE
&& uTargetIdx != VD_LAST_IMAGE, E_FAIL);
vrc = VDMerge(hdd, uSourceIdx, uTargetIdx,
task.mVDOperationIfaces);
if (RT_FAILURE(vrc))
throw vrc;
/* update parent UUIDs */
if (!task.mfMergeForward)
{
/* we need to update UUIDs of all source's children
* which cannot be part of the container at once so
* add each one in there individually */
if (task.mChildrenToReparent.size() > 0)
{
for (MediaList::const_iterator it = task.mChildrenToReparent.begin();
it != task.mChildrenToReparent.end();
++it)
{
/* VD_OPEN_FLAGS_INFO since UUID is wrong yet */
vrc = VDOpen(hdd,
(*it)->m->strFormat.c_str(),
(*it)->m->strLocationFull.c_str(),
VD_OPEN_FLAGS_INFO,
(*it)->m->vdDiskIfaces);
if (RT_FAILURE(vrc))
throw vrc;
vrc = VDSetParentUuid(hdd, VD_LAST_IMAGE,
pTarget->m->id);
if (RT_FAILURE(vrc))
throw vrc;
vrc = VDClose(hdd, false /* fDelete */);
if (RT_FAILURE(vrc))
throw vrc;
(*it)->UnlockWrite(NULL);
}
}
}
}
catch (HRESULT aRC) { rc = aRC; }
catch (int aVRC)
{
throw setError(E_FAIL,
tr("Could not merge the hard disk '%s' to '%s'%s"),
m->strLocationFull.raw(),
pTarget->m->strLocationFull.raw(),
vdError(aVRC).raw());
}
VDDestroy(hdd);
}
catch (HRESULT aRC) { rc = aRC; }
HRESULT rc2;
if (SUCCEEDED(rc))
{
/* all hard disks but the target were successfully deleted by
* VDMerge; reparent the last one and uninitialize deleted media. */
AutoWriteLock treeLock(m->pVirtualBox->getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS);
if (task.mfMergeForward)
{
/* first, unregister the target since it may become a base
* hard disk which needs re-registration */
rc2 = m->pVirtualBox->unregisterHardDisk(pTarget, NULL /*&fNeedsSaveSettings*/);
AssertComRC(rc2);
/* then, reparent it and disconnect the deleted branch at
* both ends (chain->parent() is source's parent) */
pTarget->deparent();
pTarget->m->pParent = task.mParentForTarget;
if (pTarget->m->pParent)
{
pTarget->m->pParent->m->llChildren.push_back(pTarget);
deparent();
}
/* then, register again */
rc2 = m->pVirtualBox->registerHardDisk(pTarget, NULL /*&fNeedsSaveSettings*/);
AssertComRC(rc2);
}
else
{
Assert(pTarget->getChildren().size() == 1);
Medium *targetChild = pTarget->getChildren().front();
/* disconnect the deleted branch at the elder end */
targetChild->deparent();
/* reparent source's children and disconnect the deleted
* branch at the younger end */
if (task.mChildrenToReparent.size() > 0)
{
/* obey {parent,child} lock order */
AutoWriteLock sourceLock(this COMMA_LOCKVAL_SRC_POS);
for (MediaList::const_iterator it = task.mChildrenToReparent.begin();
it != task.mChildrenToReparent.end();
it++)
{
Medium *pMedium = *it;
AutoWriteLock childLock(pMedium COMMA_LOCKVAL_SRC_POS);
pMedium->deparent(); // removes pMedium from source
pMedium->setParent(pTarget);
}
}
}
/* unregister and uninitialize all hard disks removed by the merge */
MediumLockList::Base::iterator lockListBegin =
task.mpMediumLockList->GetBegin();
MediumLockList::Base::iterator lockListEnd =
task.mpMediumLockList->GetEnd();
for (MediumLockList::Base::iterator it = lockListBegin;
it != lockListEnd;
)
{
MediumLock &mediumLock = *it;
/* Create a real copy of the medium pointer, as the medium
* lock deletion below would invalidate the referenced object. */
const ComObjPtr<Medium> pMedium = mediumLock.GetMedium();
/* The target and all images not merged (readonly) are skipped */
if ( pMedium == pTarget
|| pMedium->m->state == MediumState_LockedRead)
{
++it;
continue;
}
rc2 = pMedium->m->pVirtualBox->unregisterHardDisk(pMedium,
NULL /*pfNeedsSaveSettings*/);
AssertComRC(rc2);
/* now, uninitialize the deleted hard disk (note that
* due to the Deleting state, uninit() will not touch
* the parent-child relationship so we need to
* uninitialize each disk individually) */
/* note that the operation initiator hard disk (which is
* normally also the source hard disk) is a special case
* -- there is one more caller added by Task to it which
* we must release. Also, if we are in sync mode, the
* caller may still hold an AutoCaller instance for it
* and therefore we cannot uninit() it (it's therefore
* the caller's responsibility) */
if (pMedium == this)
{
Assert(getChildren().size() == 0);
Assert(m->backRefs.size() == 0);
task.mMediumCaller.release();
}
/* Delete the medium lock list entry, which also releases the
* caller added by MergeChain before uninit() and updates the
* iterator to point to the right place. */
rc2 = task.mpMediumLockList->RemoveByIterator(it);
AssertComRC(rc2);
if (task.isAsync() || pMedium != this)
pMedium->uninit();
}
}
if (task.isAsync())
{
// in asynchronous mode, save settings now
AutoWriteLock vboxlock(m->pVirtualBox COMMA_LOCKVAL_SRC_POS);
m->pVirtualBox->saveSettings();
}
else
// synchronous mode: report save settings result to caller
if (task.m_pfNeedsSaveSettings)
*task.m_pfNeedsSaveSettings = true;
if (FAILED(rc))
{
/* Here we come if either VDMerge() failed (in which case we
* assume that it tried to do everything to make a further
* retry possible -- e.g. not deleted intermediate hard disks
* and so on) or VirtualBox::saveSettings() failed (where we
* should have the original tree but with intermediate storage
* units deleted by VDMerge()). We have to only restore states
* (through the MergeChain dtor) unless we are run synchronously
* in which case it's the responsibility of the caller as stated
* in the mergeTo() docs. The latter also implies that we
* don't own the merge chain, so release it in this case. */
if (task.isAsync())
{
Assert(task.mChildrenToReparent.size() == 0);
cancelMergeTo(task.mChildrenToReparent, task.mpMediumLockList);
}
}
return rc;
}
/**
* Implementation code for the "clone" task.
*
* This only gets started from Medium::CloneTo() and always runs asynchronously.
* As a result, we always save the VirtualBox.xml file when we're done here.
*
* @param task
* @return
*/
HRESULT Medium::taskCloneHandler(Medium::CloneTask &task)
{
HRESULT rc = S_OK;
const ComObjPtr<Medium> &pTarget = task.mTarget;
const ComObjPtr<Medium> &pParent = task.mParent;
bool fCreatingTarget = false;
uint64_t size = 0, logicalSize = 0;
bool fGenerateUuid = false;
try
{
/* Lock all in {parent,child} order. The lock is also used as a
* signal from the task initiator (which releases it only after
* RTThreadCreate()) that we can start the job. */
AutoMultiWriteLock3 thisLock(this, pTarget, pParent COMMA_LOCKVAL_SRC_POS);
fCreatingTarget = pTarget->m->state == MediumState_Creating;
/* The object may request a specific UUID (through a special form of
* the setLocation() argument). Otherwise we have to generate it */
Guid targetId = pTarget->m->id;
fGenerateUuid = targetId.isEmpty();
if (fGenerateUuid)
{
targetId.create();
/* VirtualBox::registerHardDisk() will need UUID */
unconst(pTarget->m->id) = targetId;
}
PVBOXHDD hdd;
int vrc = VDCreate(m->vdDiskIfaces, &hdd);
ComAssertRCThrow(vrc, E_FAIL);
try
{
/* Open all hard disk images in the source chain. */
MediumLockList::Base::const_iterator sourceListBegin =
task.mpSourceMediumLockList->GetBegin();
MediumLockList::Base::const_iterator sourceListEnd =
task.mpSourceMediumLockList->GetEnd();
for (MediumLockList::Base::const_iterator it = sourceListBegin;
it != sourceListEnd;
++it)
{
const MediumLock &mediumLock = *it;
const ComObjPtr<Medium> &pMedium = mediumLock.GetMedium();
AutoReadLock alock(pMedium COMMA_LOCKVAL_SRC_POS);
/* sanity check */
Assert(pMedium->m->state == MediumState_LockedRead);
/** Open all images in read-only mode. */
vrc = VDOpen(hdd,
pMedium->m->strFormat.c_str(),
pMedium->m->strLocationFull.c_str(),
VD_OPEN_FLAGS_READONLY,
pMedium->m->vdDiskIfaces);
if (RT_FAILURE(vrc))
throw setError(E_FAIL,
tr("Could not open the hard disk storage unit '%s'%s"),
pMedium->m->strLocationFull.raw(),
vdError(vrc).raw());
}
Utf8Str targetFormat(pTarget->m->strFormat);
Utf8Str targetLocation(pTarget->m->strLocationFull);
Assert( pTarget->m->state == MediumState_Creating
|| pTarget->m->state == MediumState_LockedWrite);
Assert(m->state == MediumState_LockedRead);
Assert(pParent.isNull() || pParent->m->state == MediumState_LockedRead);
/* unlock before the potentially lengthy operation */
thisLock.release();
/* ensure the target directory exists */
rc = VirtualBox::ensureFilePathExists(targetLocation);
if (FAILED(rc))
throw rc;
PVBOXHDD targetHdd;
vrc = VDCreate(m->vdDiskIfaces, &targetHdd);
ComAssertRCThrow(vrc, E_FAIL);
try
{
/* Open all hard disk images in the target chain. */
MediumLockList::Base::const_iterator targetListBegin =
task.mpTargetMediumLockList->GetBegin();
MediumLockList::Base::const_iterator targetListEnd =
task.mpTargetMediumLockList->GetEnd();
for (MediumLockList::Base::const_iterator it = targetListBegin;
it != targetListEnd;
++it)
{
const MediumLock &mediumLock = *it;
const ComObjPtr<Medium> &pMedium = mediumLock.GetMedium();
/* If the target medium is not created yet there's no
* reason to open it. */
if (pMedium == pTarget && fCreatingTarget)
continue;
AutoReadLock alock(pMedium COMMA_LOCKVAL_SRC_POS);
/* sanity check */
Assert( pMedium->m->state == MediumState_LockedRead
|| pMedium->m->state == MediumState_LockedWrite);
/* Open all images in appropriate mode. */
vrc = VDOpen(targetHdd,
pMedium->m->strFormat.c_str(),
pMedium->m->strLocationFull.c_str(),
(pMedium->m->state == MediumState_LockedWrite) ? VD_OPEN_FLAGS_NORMAL : VD_OPEN_FLAGS_READONLY,
pMedium->m->vdDiskIfaces);
if (RT_FAILURE(vrc))
throw setError(E_FAIL,
tr("Could not open the hard disk storage unit '%s'%s"),
pMedium->m->strLocationFull.raw(),
vdError(vrc).raw());
}
/** @todo r=klaus target isn't locked, race getting the state */
vrc = VDCopy(hdd,
VD_LAST_IMAGE,
targetHdd,
targetFormat.c_str(),
(fCreatingTarget) ? targetLocation.raw() : (char *)NULL,
false,
0,
task.mVariant,
targetId.raw(),
NULL,
pTarget->m->vdDiskIfaces,
task.mVDOperationIfaces);
if (RT_FAILURE(vrc))
throw setError(E_FAIL,
tr("Could not create the clone hard disk '%s'%s"),
targetLocation.raw(), vdError(vrc).raw());
size = VDGetFileSize(targetHdd, VD_LAST_IMAGE);
logicalSize = VDGetSize(targetHdd, VD_LAST_IMAGE) / _1M;
}
catch (HRESULT aRC) { rc = aRC; }
VDDestroy(targetHdd);
}
catch (HRESULT aRC) { rc = aRC; }
VDDestroy(hdd);
}
catch (HRESULT aRC) { rc = aRC; }
/* Only do the parent changes for newly created images. */
if (SUCCEEDED(rc) && fCreatingTarget)
{
/* we set mParent & children() */
AutoWriteLock alock2(m->pVirtualBox->getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS);
Assert(pTarget->m->pParent.isNull());
if (pParent)
{
/* associate the clone with the parent and deassociate
* from VirtualBox */
pTarget->m->pParent = pParent;
pParent->m->llChildren.push_back(pTarget);
/* register with mVirtualBox as the last step and move to
* Created state only on success (leaving an orphan file is
* better than breaking media registry consistency) */
rc = pParent->m->pVirtualBox->registerHardDisk(pTarget, NULL /* pfNeedsSaveSettings */);
if (FAILED(rc))
/* break parent association on failure to register */
pTarget->deparent(); // removes target from parent
}
else
{
/* just register */
rc = m->pVirtualBox->registerHardDisk(pTarget, NULL /* pfNeedsSaveSettings */);
}
}
if (fCreatingTarget)
{
AutoWriteLock mLock(pTarget COMMA_LOCKVAL_SRC_POS);
if (SUCCEEDED(rc))
{
pTarget->m->state = MediumState_Created;
pTarget->m->size = size;
pTarget->m->logicalSize = logicalSize;
}
else
{
/* back to NotCreated on failure */
pTarget->m->state = MediumState_NotCreated;
/* reset UUID to prevent it from being reused next time */
if (fGenerateUuid)
unconst(pTarget->m->id).clear();
}
}
// now, at the end of this task (always asynchronous), save the settings
{
AutoWriteLock vboxlock(m->pVirtualBox COMMA_LOCKVAL_SRC_POS);
m->pVirtualBox->saveSettings();
}
/* Everything is explicitly unlocked when the task exits,
* as the task destruction also destroys the source chain. */
/* Make sure the source chain is released early. It could happen
* that we get a deadlock in Appliance::Import when Medium::Close
* is called & the source chain is released at the same time. */
task.mpSourceMediumLockList->Clear();
return rc;
}
/**
* Implementation code for the "delete" task.
*
* This task always gets started from Medium::deleteStorage() and can run
* synchronously or asynchrously depending on the "wait" parameter passed to
* that function.
*
* @param task
* @return
*/
HRESULT Medium::taskDeleteHandler(Medium::DeleteTask &task)
{
NOREF(task);
HRESULT rc = S_OK;
try
{
/* The lock is also used as a signal from the task initiator (which
* releases it only after RTThreadCreate()) that we can start the job */
AutoWriteLock thisLock(this COMMA_LOCKVAL_SRC_POS);
PVBOXHDD hdd;
int vrc = VDCreate(m->vdDiskIfaces, &hdd);
ComAssertRCThrow(vrc, E_FAIL);
Utf8Str format(m->strFormat);
Utf8Str location(m->strLocationFull);
/* unlock before the potentially lengthy operation */
Assert(m->state == MediumState_Deleting);
thisLock.release();
try
{
vrc = VDOpen(hdd,
format.c_str(),
location.c_str(),
VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO,
m->vdDiskIfaces);
if (RT_SUCCESS(vrc))
vrc = VDClose(hdd, true /* fDelete */);
if (RT_FAILURE(vrc))
throw setError(E_FAIL,
tr("Could not delete the hard disk storage unit '%s'%s"),
location.raw(), vdError(vrc).raw());
}
catch (HRESULT aRC) { rc = aRC; }
VDDestroy(hdd);
}
catch (HRESULT aRC) { rc = aRC; }
AutoWriteLock thisLock(this COMMA_LOCKVAL_SRC_POS);
/* go to the NotCreated state even on failure since the storage
* may have been already partially deleted and cannot be used any
* more. One will be able to manually re-open the storage if really
* needed to re-register it. */
m->state = MediumState_NotCreated;
/* Reset UUID to prevent Create* from reusing it again */
unconst(m->id).clear();
return rc;
}
/**
* Implementation code for the "reset" task.
*
* This always gets started asynchronously from Medium::Reset().
*
* @param task
* @return
*/
HRESULT Medium::taskResetHandler(Medium::ResetTask &task)
{
HRESULT rc = S_OK;
uint64_t size = 0, logicalSize = 0;
try
{
/* The lock is also used as a signal from the task initiator (which
* releases it only after RTThreadCreate()) that we can start the job */
AutoWriteLock thisLock(this COMMA_LOCKVAL_SRC_POS);
/// @todo Below we use a pair of delete/create operations to reset
/// the diff contents but the most efficient way will of course be
/// to add a VDResetDiff() API call
PVBOXHDD hdd;
int vrc = VDCreate(m->vdDiskIfaces, &hdd);
ComAssertRCThrow(vrc, E_FAIL);
Guid id = m->id;
Utf8Str format(m->strFormat);
Utf8Str location(m->strLocationFull);
Medium *pParent = m->pParent;
Guid parentId = pParent->m->id;
Utf8Str parentFormat(pParent->m->strFormat);
Utf8Str parentLocation(pParent->m->strLocationFull);
Assert(m->state == MediumState_LockedWrite);
/* unlock before the potentially lengthy operation */
thisLock.release();
try
{
/* Open all hard disk images in the target chain but the last. */
MediumLockList::Base::const_iterator targetListBegin =
task.mpMediumLockList->GetBegin();
MediumLockList::Base::const_iterator targetListEnd =
task.mpMediumLockList->GetEnd();
for (MediumLockList::Base::const_iterator it = targetListBegin;
it != targetListEnd;
++it)
{
const MediumLock &mediumLock = *it;
const ComObjPtr<Medium> &pMedium = mediumLock.GetMedium();
AutoReadLock alock(pMedium COMMA_LOCKVAL_SRC_POS);
/* sanity check, "this" is checked above */
Assert( pMedium == this
|| pMedium->m->state == MediumState_LockedRead);
/* Open all images in appropriate mode. */
vrc = VDOpen(hdd,
pMedium->m->strFormat.c_str(),
pMedium->m->strLocationFull.c_str(),
VD_OPEN_FLAGS_READONLY,
pMedium->m->vdDiskIfaces);
if (RT_FAILURE(vrc))
throw setError(E_FAIL,
tr("Could not open the hard disk storage unit '%s'%s"),
pMedium->m->strLocationFull.raw(),
vdError(vrc).raw());
/* Done when we hit the image which should be reset */
if (pMedium == this)
break;
}
/* first, delete the storage unit */
vrc = VDClose(hdd, true /* fDelete */);
if (RT_FAILURE(vrc))
throw setError(E_FAIL,
tr("Could not delete the hard disk storage unit '%s'%s"),
location.raw(), vdError(vrc).raw());
/* next, create it again */
vrc = VDOpen(hdd,
parentFormat.c_str(),
parentLocation.c_str(),
VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO,
m->vdDiskIfaces);
if (RT_FAILURE(vrc))
throw setError(E_FAIL,
tr("Could not open the hard disk storage unit '%s'%s"),
parentLocation.raw(), vdError(vrc).raw());
vrc = VDCreateDiff(hdd,
format.c_str(),
location.c_str(),
/// @todo use the same image variant as before
VD_IMAGE_FLAGS_NONE,
NULL,
id.raw(),
parentId.raw(),
VD_OPEN_FLAGS_NORMAL,
m->vdDiskIfaces,
task.mVDOperationIfaces);
if (RT_FAILURE(vrc))
throw setError(E_FAIL,
tr("Could not create the differencing hard disk storage unit '%s'%s"),
location.raw(), vdError(vrc).raw());
size = VDGetFileSize(hdd, VD_LAST_IMAGE);
logicalSize = VDGetSize(hdd, VD_LAST_IMAGE) / _1M;
}
catch (HRESULT aRC) { rc = aRC; }
VDDestroy(hdd);
}
catch (HRESULT aRC) { rc = aRC; }
AutoWriteLock thisLock(this COMMA_LOCKVAL_SRC_POS);
m->size = size;
m->logicalSize = logicalSize;
if (task.isAsync())
{
/* unlock ourselves when done */
HRESULT rc2 = UnlockWrite(NULL);
AssertComRC(rc2);
}
/* Note that in sync mode, it's the caller's responsibility to
* unlock the hard disk */
return rc;
}
/**
* Implementation code for the "compact" task.
*
* @param task
* @return
*/
HRESULT Medium::taskCompactHandler(Medium::CompactTask &task)
{
HRESULT rc = S_OK;
/* Lock all in {parent,child} order. The lock is also used as a
* signal from the task initiator (which releases it only after
* RTThreadCreate()) that we can start the job. */
AutoWriteLock thisLock(this COMMA_LOCKVAL_SRC_POS);
try
{
PVBOXHDD hdd;
int vrc = VDCreate(m->vdDiskIfaces, &hdd);
ComAssertRCThrow(vrc, E_FAIL);
try
{
/* Open all hard disk images in the chain. */
MediumLockList::Base::const_iterator mediumListBegin =
task.mpMediumLockList->GetBegin();
MediumLockList::Base::const_iterator mediumListEnd =
task.mpMediumLockList->GetEnd();
MediumLockList::Base::const_iterator mediumListLast =
mediumListEnd;
mediumListLast--;
for (MediumLockList::Base::const_iterator it = mediumListBegin;
it != mediumListEnd;
++it)
{
const MediumLock &mediumLock = *it;
const ComObjPtr<Medium> &pMedium = mediumLock.GetMedium();
AutoReadLock alock(pMedium COMMA_LOCKVAL_SRC_POS);
/* sanity check */
if (it == mediumListLast)
Assert(pMedium->m->state == MediumState_LockedWrite);
else
Assert(pMedium->m->state == MediumState_LockedRead);
/** Open all images but last in read-only mode. */
vrc = VDOpen(hdd,
pMedium->m->strFormat.c_str(),
pMedium->m->strLocationFull.c_str(),
(it == mediumListLast) ? VD_OPEN_FLAGS_NORMAL : VD_OPEN_FLAGS_READONLY,
pMedium->m->vdDiskIfaces);
if (RT_FAILURE(vrc))
throw setError(E_FAIL,
tr("Could not open the hard disk storage unit '%s'%s"),
pMedium->m->strLocationFull.raw(),
vdError(vrc).raw());
}
Assert(m->state == MediumState_LockedWrite);
Utf8Str location(m->strLocationFull);
/* unlock before the potentially lengthy operation */
thisLock.release();
vrc = VDCompact(hdd, VD_LAST_IMAGE, task.mVDOperationIfaces);
if (RT_FAILURE(vrc))
{
if (vrc == VERR_NOT_SUPPORTED)
throw setError(VBOX_E_NOT_SUPPORTED,
tr("Compacting is not yet supported for hard disk '%s'"),
location.raw());
else if (vrc == VERR_NOT_IMPLEMENTED)
throw setError(E_NOTIMPL,
tr("Compacting is not implemented, hard disk '%s'"),
location.raw());
else
throw setError(E_FAIL,
tr("Could not compact hard disk '%s'%s"),
location.raw(),
vdError(vrc).raw());
}
}
catch (HRESULT aRC) { rc = aRC; }
VDDestroy(hdd);
}
catch (HRESULT aRC) { rc = aRC; }
/* Everything is explicitly unlocked when the task exits,
* as the task destruction also destroys the image chain. */
return rc;
}
/* vi: set tabstop=4 shiftwidth=4 expandtab: */