SnapshotImpl.cpp revision 7ce6b6c3210a3256cc3bb49c213fea445e7d0fa1
/** @file
*
* VirtualBox COM class implementation
*/
/*
* Copyright (C) 2006-2007 Sun Microsystems, Inc.
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* General Public License (GPL) as published by the Free Software
* Foundation, in version 2 as it comes in the "COPYING" file of the
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
* Clara, CA 95054 USA or visit http://www.sun.com if you need
* additional information or have any questions.
*/
#include "SnapshotImpl.h"
#include "MachineImpl.h"
#include "Logging.h"
#include <list>
#include <VBox/settings.h>
// private snapshot data
////////////////////////////////////////////////////////////////////////////////
{
Data()
{
RTTimeSpecSetMilli(&timeStamp, 0);
};
~Data()
{}
};
// constructor / destructor
////////////////////////////////////////////////////////////////////////////////
{
LogFlowMember (("Snapshot::FinalConstruct()\n"));
return S_OK;
}
void Snapshot::FinalRelease()
{
LogFlowMember (("Snapshot::FinalRelease()\n"));
uninit();
}
/**
* Initializes the instance
*
* @param aId id of the snapshot
* @param aName name of the snapshot
* @param aDescription name of the snapshot (NULL if no description)
* @param aTimeStamp timestamp of the snapshot, in ms since 1970-01-01 UTC
* @param aMachine machine associated with this snapshot
* @param aParent parent snapshot (NULL if no parent)
*/
{
/* Enclose the state transition NotReady->InInit->Ready */
AutoInitSpan autoInitSpan(this);
m = new Data;
/* share parent weakly */
m->description = aDescription;
m->timeStamp = aTimeStamp;
if (aParent)
/* Confirm a successful initialization when it's the case */
return S_OK;
}
/**
* Uninitializes the instance and sets the ready flag to FALSE.
* Called either from FinalRelease(), by the parent when it gets destroyed,
* or by a third party when it decides this object is no more valid.
*/
{
LogFlowMember (("Snapshot::uninit()\n"));
/* Enclose the state transition Ready->InUninit->NotReady */
AutoUninitSpan autoUninitSpan (this);
if (autoUninitSpan.uninitDone())
return;
// uninit all children
++it)
{
}
if (mParent)
{
++ it)
{
if (this == pParentsChild)
{
break;
}
}
}
if (m->pMachine)
{
}
delete m;
m = NULL;
}
/**
* Discards the current snapshot by removing it from the tree of snapshots
* and reparenting its children.
*
* After this, the caller must call uninit() on the snapshot. We can't call
* that from here because if we do, the AutoUninitSpan waits forever for
* the number of callers to become 0 (it is 1 because of the AutoCaller in here).
*
* NOTE: this does NOT lock the snapshot, it is assumed that the caller has
* locked a) the machine and b) the snapshots tree in write mode!
*/
void Snapshot::beginDiscard()
{
AutoCaller autoCaller(this);
return;
/* for now, the snapshot must have only one child when discarded,
* or no children at all */
/// @todo (dmik):
// when we introduce clones later, discarding the snapshot
// will affect the current and first snapshots of clones, if they are
// direct children of this snapshot. So we will need to lock machines
// associated with child snapshots as well and update mCurrentSnapshot
{
/* we've changed the base of the current state so mark it as
* modified as it no longer guaranteed to be its copy */
}
{
{
}
else
}
// reparent our children
++it)
{
if (mParent)
}
// clear our own children list (since we reparented the children)
m->llChildren.clear();
}
// ISnapshot methods
////////////////////////////////////////////////////////////////////////////////
{
AutoCaller autoCaller(this);
AutoReadLock alock (this);
return S_OK;
}
{
AutoCaller autoCaller(this);
AutoReadLock alock (this);
return S_OK;
}
/**
* @note Locks this object for writing, then calls Machine::onSnapshotChange()
* (see its lock requirements).
*/
{
AutoCaller autoCaller(this);
AutoWriteLock alock(this);
{
return m->pMachine->onSnapshotChange(this);
}
return S_OK;
}
{
AutoCaller autoCaller(this);
AutoReadLock alock (this);
return S_OK;
}
{
AutoCaller autoCaller(this);
AutoWriteLock alock(this);
if (m->description != aDescription)
{
m->description = aDescription;
return m->pMachine->onSnapshotChange(this);
}
return S_OK;
}
{
AutoCaller autoCaller(this);
AutoReadLock alock (this);
return S_OK;
}
{
AutoCaller autoCaller(this);
AutoReadLock alock (this);
return S_OK;
}
{
AutoCaller autoCaller(this);
AutoReadLock alock (this);
return S_OK;
}
{
AutoCaller autoCaller(this);
AutoReadLock alock (this);
return S_OK;
}
{
AutoCaller autoCaller(this);
return S_OK;
}
// public methods only for internal purposes
////////////////////////////////////////////////////////////////////////////////
/**
* @note
* Must be called from under the object's lock!
*/
{
}
/**
* Returns the number of direct child snapshots, without grandchildren.
* Does not recurse.
* @return
*/
{
AutoCaller autoCaller(this);
}
/**
* Implementation method for getAllChildrenCount() so we request the
* tree lock only once before recursing. Don't call directly.
* @return
*/
{
AutoCaller autoCaller(this);
++it)
{
}
return count;
}
/**
* Returns the number of child snapshots including all grandchildren.
* Recurses into the snapshots tree.
* @return
*/
{
AutoCaller autoCaller(this);
return getAllChildrenCountImpl();
}
/**
* Returns the SnapshotMachine that this snapshot belongs to.
* Caller must hold the snapshot's object lock!
* @return
*/
{
return (SnapshotMachine*)m->pMachine;
}
/**
* Returns the UUID of this snapshot.
* Caller must hold the snapshot's object lock!
* @return
*/
{
return m->id;
}
/**
* Returns the name of this snapshot.
* Caller must hold the snapshot's object lock!
* @return
*/
{
return m->name;
}
/**
* Returns the time stamp of this snapshot.
* Caller must hold the snapshot's object lock!
* @return
*/
{
return m->timeStamp;
}
/**
* Searches for a snapshot with the given ID among children, grand-children,
* etc. of this snapshot. This snapshot itself is also included in the search.
* Caller must hold the snapshots tree lock!
*/
{
AutoCaller autoCaller(this);
AutoReadLock alock(this);
child = this;
else
{
++it)
{
break;
}
}
return child;
}
/**
* Searches for a first snapshot with the given name among children,
* grand-children, etc. of this snapshot. This snapshot itself is also included
* in the search.
* Caller must hold the snapshots tree lock!
*/
{
AutoCaller autoCaller(this);
AutoReadLock alock (this);
child = this;
else
{
++it)
{
break;
}
}
return child;
}
/**
* Internal implementation for Snapshot::updateSavedStatePaths (below).
* @param aOldPath
* @param aNewPath
*/
{
AutoWriteLock alock(this);
/* state file may be NULL (for offline snapshots) */
)
{
}
++it)
{
}
}
/**
* Checks if the specified path change affects the saved state file path of
* this snapshot or any of its (grand-)children and updates it accordingly.
*
* Intended to be called by Machine::openConfigLoader() only.
*
* @param aOldPath old path (full)
* @param aNewPath new path (full)
*
* @note Locks this object + children for writing.
*/
{
AutoCaller autoCaller(this);
// call the implementation under the tree lock
}
/**
* Internal implementation for Snapshot::saveSnapshot (below).
* @param aNode
* @param aAttrsOnly
* @return
*/
{
using namespace settings;
AutoReadLock alock(this);
/* uuid (required) */
if (!aAttrsOnly)
/* name (required) */
/* timeStamp (required) */
/* Description node (optional) */
if (!m->description.isNull())
{
}
else
{
}
if (aAttrsOnly)
return S_OK;
/* stateFile (optional) */
if (stateFilePath())
{
/* try to make the file name relative to the settings file dir */
}
{
/* save hardware */
{
}
/* save hard disks. */
{
}
}
if (m->llChildren.size())
{
++it)
{
}
}
return S_OK;
}
/**
* Saves the given snapshot and all its children (unless \a aAttrsOnly is true).
* It is assumed that the given node is empty (unless \a aAttrsOnly is true).
*
* @param aNode <Snapshot> node to save the snapshot to.
* @param aSnapshot Snapshot to save.
* @param aAttrsOnly If true, only updatge user-changeable attrs.
*/
{
}