On 06/12/2012 05:27 PM, Eric Blake wrote: > I'm off on my versioning - this was 0.9.6 and earlier. > >> if (from) { > > There's multiple things going on here: > > First, the valid combinations: > > Then the API that satisfy those combinations: > > I really need to list this as a comment. I'll post a v2, adding > comments and including your improvements. Here's what I'll squash for my v2: diff --git i/tools/virsh.c w/tools/virsh.c index 768d189..537496f 100644 --- i/tools/virsh.c +++ w/tools/virsh.c @@ -16848,7 +16848,7 @@ vshSnapshotListCollect(vshControl *ctl, virDomainPtr dom, { int i; char **names = NULL; - int count = 0; + int count = -1; bool descendants = false; bool roots = false; vshSnapshotListPtr snaplist = vshMalloc(ctl, sizeof(*snaplist)); @@ -16859,8 +16859,24 @@ vshSnapshotListCollect(vshControl *ctl, virDomainPtr dom, /* 0.9.13 will be adding a new listing API. */ - /* This is the interface available in 0.9.12 and earlier, - * including fallbacks to 0.9.4 and earlier. */ + /* This uses the interfaces available in 0.8.0-0.9.6 + * (virDomainSnapshotListNames, global list only) and in + * 0.9.7-0.9.12 (addition of virDomainSnapshotListChildrenNames + * for child listing, and new flags), as follows, with [*] by the + * combinations that need parent info (either for filtering + * purposes or for the resulting tree listing): + * old new + * list global as-is global as-is + * list --roots *global + filter global + flags + * list --from *global + filter child + flags + * list --from --descendants *global + filter child + flags + * list --tree *global as-is *global as-is + * list --tree --from *global + filter *child + flags + * + * Additionally, when --tree and --from are both used, from is + * added to the final list as the only element without a parent. + * Otherwise, --from does not appear in the final list. + */ if (from) { fromname = virDomainSnapshotGetName(from); if (!fromname) { @@ -16870,28 +16886,30 @@ vshSnapshotListCollect(vshControl *ctl, virDomainPtr dom, descendants = (flags & VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS) != 0; if (tree) flags |= VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS; - count = ctl->useSnapshotOld ? -1 : - virDomainSnapshotNumChildren(from, flags); - if (count < 0) { - if (ctl->useSnapshotOld || - last_error->code == VIR_ERR_NO_SUPPORT) { - /* We can emulate --from. */ - /* XXX can we also emulate --leaves? */ - virFreeError(last_error); - last_error = NULL; - ctl->useSnapshotOld = true; - flags &= ~VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS; - count = virDomainSnapshotNum(dom, flags); - } - } else if (tree) { - count++; + + /* First, determine if we can use the new child listing API. */ + if (!ctl->useSnapshotOld && + (count = virDomainSnapshotNumChildren(from, flags) < 0) && + last_error->code == VIR_ERR_NO_SUPPORT) { + /* We can emulate --from. */ + /* XXX can we also emulate --leaves? */ + virFreeError(last_error); + last_error = NULL; + ctl->useSnapshotOld = true; + flags &= ~VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS; } - } else { + if (tree && count >= 0) + count++; + } + + /* Global listing (including fallback when --from failed with + * child listing). */ + if (count < 0) { count = virDomainSnapshotNum(dom, flags); /* Fall back to simulation if --roots was unsupported. */ /* XXX can we also emulate --leaves? */ - if (count < 0 && last_error->code == VIR_ERR_INVALID_ARG && + if (!from && count < 0 && last_error->code == VIR_ERR_INVALID_ARG && (flags & VIR_DOMAIN_SNAPSHOT_LIST_ROOTS)) { virFreeError(last_error); last_error = NULL; @@ -16903,7 +16921,7 @@ vshSnapshotListCollect(vshControl *ctl, virDomainPtr dom, if (count < 0) { if (!last_error) - vshError(ctl, _("missing support")); + vshError(ctl, _("failed to collect snapshot list")); goto cleanup; } @@ -16912,6 +16930,7 @@ vshSnapshotListCollect(vshControl *ctl, virDomainPtr dom, names = vshCalloc(ctl, sizeof(*names), count); + /* Now that we have a count, collect the list. */ if (from && !ctl->useSnapshotOld) { if (tree) { if (count) @@ -16940,6 +16959,10 @@ vshSnapshotListCollect(vshControl *ctl, virDomainPtr dom, goto cleanup; } + /* Collect parents when needed. With the new API, --tree and + * --from together put from as the first element without a parent; + * with the old API we still need to do a post-process filtering + * based on all parent information. */ if (tree || (from && ctl->useSnapshotOld)) { for (i = (from && !ctl->useSnapshotOld); i < count; i++) { if (from && ctl->useSnapshotOld && STREQ(names[i], fromname)) { -- Eric Blake eblake@xxxxxxxxxx +1-919-301-3266 Libvirt virtualization library http://libvirt.org
Attachment:
signature.asc
Description: OpenPGP digital signature
-- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list