mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-26 22:45:17 +00:00
snapshots: Support topological visits
Wire up support for VIR_DOMAIN_SNAPSHOT_LIST_TOPOLOGICAL in the domain-agnostic support code. Clients of snapshot_conf using virDomainSnapshotForEachDescendant() are using a depth-first visit but with postfix visits of a given node. Changing this to a prefix visit of the given node instantly turns this into a topologically-ordered visit. (A prefix breadth-first visit would also be topologically sorted, but that requires a queue while our recursion naturally has a stack). With that change, we now always have a topological sort for virDomainSnapshotListAllChildren() regardless of the new public API flag. Then with one more tweak, we can also get a topological rather than a faster random hash visit for virDomainListAllSnapshots(), by doing a descendent walk from our internal metaroot (there, we let the public API flag control behavior, because a topological sort DOES require more stack and slightly more time). Note that virDomainSnapshotForEach() still uses a random hash visit; we could change that signature to take a tri-state for random, prefix, or postfix visit if we ever had clients that cared about the distinctions, but for now, none of the drivers seem to care. Signed-off-by: Eric Blake <eblake@redhat.com> Reviewed-by: Ján Tomko <jtomko@redhat.com> Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
This commit is contained in:
parent
d16e5b15ed
commit
b647d2195d
@ -1213,9 +1213,10 @@ virDomainSnapshotObjListGetNames(virDomainSnapshotObjListPtr snapshots,
|
|||||||
from = &snapshots->metaroot;
|
from = &snapshots->metaroot;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We handle LIST_ROOT/LIST_DESCENDANTS directly, mask that bit
|
/* We handle LIST_ROOT/LIST_DESCENDANTS and LIST_TOPOLOGICAL directly,
|
||||||
* out to determine when we must use the filter callback. */
|
* mask those bits out to determine when we must use the filter callback. */
|
||||||
data.flags &= ~VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS;
|
data.flags &= ~(VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS |
|
||||||
|
VIR_DOMAIN_SNAPSHOT_LIST_TOPOLOGICAL);
|
||||||
|
|
||||||
/* If this common code is being used, we assume that all snapshots
|
/* If this common code is being used, we assume that all snapshots
|
||||||
* have metadata, and thus can handle METADATA up front as an
|
* have metadata, and thus can handle METADATA up front as an
|
||||||
@ -1240,7 +1241,11 @@ virDomainSnapshotObjListGetNames(virDomainSnapshotObjListPtr snapshots,
|
|||||||
data.flags &= ~VIR_DOMAIN_SNAPSHOT_FILTERS_LOCATION;
|
data.flags &= ~VIR_DOMAIN_SNAPSHOT_FILTERS_LOCATION;
|
||||||
|
|
||||||
if (flags & VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS) {
|
if (flags & VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS) {
|
||||||
if (from->def)
|
/* We could just always do a topological visit; but it is
|
||||||
|
* possible to optimize for less stack usage and time when a
|
||||||
|
* simpler full hashtable visit or counter will do. */
|
||||||
|
if (from->def || (names &&
|
||||||
|
(flags & VIR_DOMAIN_SNAPSHOT_LIST_TOPOLOGICAL)))
|
||||||
virDomainSnapshotForEachDescendant(from,
|
virDomainSnapshotForEachDescendant(from,
|
||||||
virDomainSnapshotObjListCopyNames,
|
virDomainSnapshotObjListCopyNames,
|
||||||
&data);
|
&data);
|
||||||
@ -1327,10 +1332,10 @@ virDomainSnapshotActOnDescendant(void *payload,
|
|||||||
virDomainSnapshotObjPtr obj = payload;
|
virDomainSnapshotObjPtr obj = payload;
|
||||||
struct snapshot_act_on_descendant *curr = data;
|
struct snapshot_act_on_descendant *curr = data;
|
||||||
|
|
||||||
|
(curr->iter)(payload, name, curr->data);
|
||||||
curr->number += 1 + virDomainSnapshotForEachDescendant(obj,
|
curr->number += 1 + virDomainSnapshotForEachDescendant(obj,
|
||||||
curr->iter,
|
curr->iter,
|
||||||
curr->data);
|
curr->data);
|
||||||
(curr->iter)(payload, name, curr->data);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user