mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-10-13 17:49:16 +00:00
02c4e24db7
Rather than allowing a leaky abstraction where multiple drivers have to open-code operations that update the relations in a virDomainSnapshotObjList, it is better to add accessor functions so that updates to relations are maintained closer to the internals. This patch finishes the job started in the previous patch, by getting rid of all direct access to nchildren, first_child, or sibling outside of the lowest level functions, making it easier to refactor later on. The lone new caller to virDomainSnapshotObjListSize() checks for a return != 0, because it wants to handles errors (-1, only possible if the hash table wasn't allocated) and existing snapshots (> 0) in the same manner; we can drop the check for a current snapshot on the grounds that there shouldn't be one if there are no snapshots. Signed-off-by: Eric Blake <eblake@redhat.com> Reviewed-by: John Ferlan <jferlan@redhat.com>
168 lines
4.9 KiB
C
168 lines
4.9 KiB
C
/*
|
|
* virdomainsnapshotobj.c: handle snapshot objects
|
|
* (derived from snapshot_conf.c)
|
|
*
|
|
* Copyright (C) 2006-2019 Red Hat, Inc.
|
|
* Copyright (C) 2006-2008 Daniel P. Berrange
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library. If not, see
|
|
* <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include <config.h>
|
|
|
|
#include "internal.h"
|
|
#include "virdomainsnapshotobj.h"
|
|
#include "snapshot_conf.h"
|
|
#include "virdomainsnapshotobjlist.h"
|
|
#include "virlog.h"
|
|
#include "virerror.h"
|
|
|
|
#define VIR_FROM_THIS VIR_FROM_DOMAIN_SNAPSHOT
|
|
|
|
VIR_LOG_INIT("conf.virdomainsnapshotobj");
|
|
|
|
/* Run iter(data) on all direct children of snapshot, while ignoring all
|
|
* other entries in snapshots. Return the number of children
|
|
* visited. No particular ordering is guaranteed. */
|
|
int
|
|
virDomainSnapshotForEachChild(virDomainSnapshotObjPtr snapshot,
|
|
virHashIterator iter,
|
|
void *data)
|
|
{
|
|
virDomainSnapshotObjPtr child = snapshot->first_child;
|
|
|
|
while (child) {
|
|
virDomainSnapshotObjPtr next = child->sibling;
|
|
(iter)(child, child->def->name, data);
|
|
child = next;
|
|
}
|
|
|
|
return snapshot->nchildren;
|
|
}
|
|
|
|
struct snapshot_act_on_descendant {
|
|
int number;
|
|
virHashIterator iter;
|
|
void *data;
|
|
};
|
|
|
|
static int
|
|
virDomainSnapshotActOnDescendant(void *payload,
|
|
const void *name,
|
|
void *data)
|
|
{
|
|
virDomainSnapshotObjPtr obj = payload;
|
|
struct snapshot_act_on_descendant *curr = data;
|
|
|
|
(curr->iter)(payload, name, curr->data);
|
|
curr->number += 1 + virDomainSnapshotForEachDescendant(obj,
|
|
curr->iter,
|
|
curr->data);
|
|
return 0;
|
|
}
|
|
|
|
/* Run iter(data) on all descendants of snapshot, while ignoring all
|
|
* other entries in snapshots. Return the number of descendants
|
|
* visited. The visit is guaranteed to be topological, but no
|
|
* particular order between siblings is guaranteed. */
|
|
int
|
|
virDomainSnapshotForEachDescendant(virDomainSnapshotObjPtr snapshot,
|
|
virHashIterator iter,
|
|
void *data)
|
|
{
|
|
struct snapshot_act_on_descendant act;
|
|
|
|
act.number = 0;
|
|
act.iter = iter;
|
|
act.data = data;
|
|
virDomainSnapshotForEachChild(snapshot,
|
|
virDomainSnapshotActOnDescendant, &act);
|
|
|
|
return act.number;
|
|
}
|
|
|
|
|
|
/* Prepare to reparent or delete snapshot, by removing it from its
|
|
* current listed parent. Note that when bulk removing all children
|
|
* of a parent, it is faster to just 0 the count rather than calling
|
|
* this function on each child. */
|
|
void
|
|
virDomainSnapshotDropParent(virDomainSnapshotObjPtr snapshot)
|
|
{
|
|
virDomainSnapshotObjPtr prev = NULL;
|
|
virDomainSnapshotObjPtr curr = NULL;
|
|
|
|
snapshot->parent->nchildren--;
|
|
curr = snapshot->parent->first_child;
|
|
while (curr != snapshot) {
|
|
if (!curr) {
|
|
VIR_WARN("inconsistent snapshot relations");
|
|
return;
|
|
}
|
|
prev = curr;
|
|
curr = curr->sibling;
|
|
}
|
|
if (prev)
|
|
prev->sibling = snapshot->sibling;
|
|
else
|
|
snapshot->parent->first_child = snapshot->sibling;
|
|
snapshot->parent = NULL;
|
|
snapshot->sibling = NULL;
|
|
}
|
|
|
|
|
|
/* Update @snapshot to no longer have children. */
|
|
void
|
|
virDomainSnapshotDropChildren(virDomainSnapshotObjPtr snapshot)
|
|
{
|
|
snapshot->nchildren = 0;
|
|
snapshot->first_child = NULL;
|
|
}
|
|
|
|
|
|
/* Add @snapshot to @parent's list of children. */
|
|
void
|
|
virDomainSnapshotSetParent(virDomainSnapshotObjPtr snapshot,
|
|
virDomainSnapshotObjPtr parent)
|
|
{
|
|
snapshot->parent = parent;
|
|
parent->nchildren++;
|
|
snapshot->sibling = parent->first_child;
|
|
parent->first_child = snapshot;
|
|
}
|
|
|
|
|
|
/* Take all children of @from and convert them into children of @to. */
|
|
void
|
|
virDomainSnapshotMoveChildren(virDomainSnapshotObjPtr from,
|
|
virDomainSnapshotObjPtr to)
|
|
{
|
|
virDomainSnapshotObjPtr child;
|
|
virDomainSnapshotObjPtr last;
|
|
|
|
if (!from->first_child)
|
|
return;
|
|
for (child = from->first_child; child; child = child->sibling) {
|
|
child->parent = to;
|
|
if (!child->sibling)
|
|
last = child;
|
|
}
|
|
to->nchildren += from->nchildren;
|
|
last->sibling = to->first_child;
|
|
to->first_child = from->first_child;
|
|
from->nchildren = 0;
|
|
from->first_child = NULL;
|
|
}
|