On Thu, May 19, 2011 at 04:51:29PM -0400, Laine Stump wrote: > From: Michal Privoznik <mpriv...@redhat.com> > > --- > src/conf/interface_conf.c | 45 ++++++++++++++++++++++++ > src/conf/interface_conf.h | 4 ++ > src/test/test_driver.c | 83 > +++++++++++++++++++++++++++++++++++++++++++++ > 3 files changed, 132 insertions(+), 0 deletions(-) > > diff --git a/src/conf/interface_conf.c b/src/conf/interface_conf.c > index f3848bd..4ff68aa 100644 > --- a/src/conf/interface_conf.c > +++ b/src/conf/interface_conf.c > @@ -1227,6 +1227,51 @@ void virInterfaceObjListFree(virInterfaceObjListPtr > interfaces) > interfaces->count = 0; > } > > +int virInterfaceObjListClone(virConnectPtr conn, > + virInterfaceObjListPtr src, > + virInterfaceObjListPtr dest) > +{ > + int ret = -1; > + unsigned int i, cnt; > + > + if (!src || !dest) > + goto end; > + > + cnt = src->count; > + for (i = 0; i < cnt; i++) { > + virInterfaceDefPtr def = src->objs[i]->def; > + virInterfaceDefPtr backup; > + virInterfaceObjPtr iface; > + char *xml = virInterfaceDefFormat(def); > + > + if (!xml) { > + virReportOOMError(); > + goto no_memory; > + } > + > + if ((backup = virInterfaceDefParseString(xml)) == NULL) { > + VIR_FREE(xml); > + goto no_memory; > + } > + > + VIR_FREE(xml); > + if ((iface = virInterfaceAssignDef(dest, backup)) == NULL) > + goto no_memory; > + > + virInterfaceObjUnlock(iface); > + > + conn->refs++; > + } > + > + ret = cnt; > +end: > + return ret; > + > +no_memory: > + virInterfaceObjListFree(dest);
I'ts always a problem when the callee frees up memory allocated by the caller in case of error, as it's so easy to mess things up. I would rather not do that here, and have the caller do the free if we fail. example: src == NULL, dest != NULL, and we leak dest. > + goto end; > +} > + > virInterfaceObjPtr virInterfaceAssignDef(virInterfaceObjListPtr interfaces, > const virInterfaceDefPtr def) > { > diff --git a/src/conf/interface_conf.h b/src/conf/interface_conf.h > index 6073b49..870a8ee 100644 > --- a/src/conf/interface_conf.h > +++ b/src/conf/interface_conf.h > @@ -192,6 +192,10 @@ virInterfaceObjPtr virInterfaceFindByName(const > virInterfaceObjListPtr > void virInterfaceDefFree(virInterfaceDefPtr def); > void virInterfaceObjFree(virInterfaceObjPtr iface); > void virInterfaceObjListFree(virInterfaceObjListPtr vms); > +int virInterfaceObjListClone(virConnectPtr conn, > + virInterfaceObjListPtr src, > + virInterfaceObjListPtr dest); > + > > virInterfaceObjPtr virInterfaceAssignDef(virInterfaceObjListPtr interfaces, > const virInterfaceDefPtr def); > diff --git a/src/test/test_driver.c b/src/test/test_driver.c > index e86bc4e..b58c5d2 100644 > --- a/src/test/test_driver.c > +++ b/src/test/test_driver.c > @@ -85,6 +85,8 @@ struct _testConn { > virDomainObjList domains; > virNetworkObjList networks; > virInterfaceObjList ifaces; > + bool transaction_running; > + virInterfaceObjList backupIfaces; > virStoragePoolObjList pools; > virNodeDeviceObjList devs; > int numCells; > @@ -3455,6 +3457,84 @@ cleanup: > return ret; > } > > +static int testInterfaceChangeBegin(virConnectPtr conn, > + unsigned int flags ATTRIBUTE_UNUSED) > +{ > + testConnPtr privconn = conn->privateData; > + int ret = -1; > + > + testDriverLock(privconn); > + if (privconn->transaction_running) { > + testError(VIR_ERR_OPERATION_INVALID, _("there is another transaction > " > + "running.")); > + goto cleanup; > + } > + > + privconn->transaction_running = true; > + > + if (virInterfaceObjListClone(conn, &privconn->ifaces, > + &privconn->backupIfaces) < 0) > + goto cleanup; > + > + ret = 0; > +cleanup: > + testDriverUnlock(privconn); > + return ret; > +} > + > +static int testInterfaceChangeCommit(virConnectPtr conn, > + unsigned int flags ATTRIBUTE_UNUSED) > +{ > + testConnPtr privconn = conn->privateData; > + int ret = -1; > + > + testDriverLock(privconn); > + > + if (!privconn->transaction_running) { > + testError(VIR_ERR_OPERATION_INVALID, _("no transaction running, " > + "nothing to be commited.")); > + goto cleanup; > + } > + > + virInterfaceObjListFree(&privconn->backupIfaces); > + privconn->transaction_running = false; > + > + ret = 0; > + > +cleanup: > + testDriverUnlock(privconn); > + > + return ret; > +} > + > +static int testInterfaceChangeRollback(virConnectPtr conn, > + unsigned int flags ATTRIBUTE_UNUSED) > +{ > + testConnPtr privconn = conn->privateData; > + int ret = -1; > + > + testDriverLock(privconn); > + > + if (!privconn->transaction_running) { > + testError(VIR_ERR_OPERATION_INVALID, _("no transaction running, " > + "nothing to rollback.")); > + goto cleanup; > + } > + > + virInterfaceObjListFree(&privconn->ifaces); > + privconn->ifaces.count = privconn->backupIfaces.count; > + privconn->ifaces.objs = privconn->backupIfaces.objs; > + privconn->backupIfaces.count = 0; > + privconn->backupIfaces.objs = NULL; > + > + privconn->transaction_running = false; > + > + ret = 0; > + > +cleanup: > + testDriverUnlock(privconn); > + return ret; > +} > > static char *testInterfaceGetXMLDesc(virInterfacePtr iface, > unsigned int flags ATTRIBUTE_UNUSED) > @@ -5428,6 +5508,9 @@ static virInterfaceDriver testInterfaceDriver = { > .interfaceCreate = testInterfaceCreate, /* 0.7.0 */ > .interfaceDestroy = testInterfaceDestroy, /* 0.7.0 */ > .interfaceIsActive = testInterfaceIsActive, /* 0.7.3 */ > + .interfaceChangeBegin = testInterfaceChangeBegin, /* 0.9.2 */ > + .interfaceChangeCommit = testInterfaceChangeCommit, /* 0.9.2 */ > + .interfaceChangeRollback = testInterfaceChangeRollback, /* 0.9.2 */ > }; Except for the small nit on how virInterfaceObjListClone() handle errors, fine, and ACK once fixed (just do the free in the caller on error). Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ dan...@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/ -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list