
[Resurrecting this old thread which has just been brought to my attention] On Fri, Sep 10, 2010 at 05:00:52PM +0100, Daniel P. Berrange wrote:
typedef struct _virLockManagerDriver virLockManagerDriver; typedef virLockManagerDriver *virLockManagerDriverPtr;
/* Which callbacks are supported */ typedef enum { VIR_LOCK_MANAGER_DRIVER_RESOURCES = (1 << 0), VIR_LOCK_MANAGER_DRIVER_MIGRATE = (1 << 0), VIR_LOCK_MANAGER_DRIVER_HOTPLUG = (1 << 1), };
struct _virLockManagerDriver { /** * @version: the newest implemented plugin ABI version * @flags: the implemented plugin optional extras */ unsigned int version; unsigned int flags;
/** * load_drv: * @version: the libvirt requested plugin ABI version * @flags: the libvirt requested plugin optional extras * * Allow the plugin to validate the libvirt requested * plugin version / flags. This allows it to reject * use of versions which are too old. A plugin may * be loaded multiple times, for different libvirt * drivers * * Returns -1 if the requested version/flags were inadequate */ int (*load_drv)(unsigned int version, unsigned int flags);
/** * unload_drv: * * Called to release any resources prior to the plugin * being unloaded from memory. Returns -1 to prevent * plugin unloading. */ int (*[un]load_drv)(void);
There are various user-unfriendly aspects to this: (1) If load_drv fails, you've left me up the creek. What can I as a caller do? Tell the user to upgrade their software? Carry on regardless? (2) Without compiler help it is hard to call load_drv/unload_drv at the right time in a thread-safe way. (3) Having all the functions buried inside a structure means I cannot use ordinary techniques (ie. dlsym) to find out if a function is supported. Because I cannot use dlsym, I'm forced to use hard-coded ABI checks! I think this is better done using the techniques that ELF or any self-respecting dynamic loader already provides: Use __attribute__((constructor)) and __attribute__((destructor)) to automatically and safely start and stop the lock manager (solves (2)). Guarantee a minimum ABI in the first version (solves (1)). Provide top-level functions in the lockmgr.so which correspond to functions I can call directly, ie: virLockManagerDoFoo (virLockManagerPtr *impl, int foo_arg); and let me find out if they are supported by calling dlsym (solves (1) & (3)). If you need to change an API, add another function: virLockManagerDoFoo2 (virLockManagerPtr *impl, int foo_arg, int oops_we_forgot_this_arg); As for the specifics, where is the lock manager DSO going to sit in the filesystem? Thanks for explaining the specifics of this on IRC. It currently looks like this: impl->load_drv(LIBVIRT_LOCK_VERSION, 0); impl->new_drv(VIR_LOCK_MANAGER_OBJECT_TYPE_DOMAIN, 0); impl->set_parameter_drv("id", 2); impl->set_parameter_drv("name", "foo-guest'); impl->set_parameter_drv("uuid", "c7a2edbd-edaf-9455-926a-d65c16db1809"); impl->acquire_resource(VIR_LOCK_MANAGER_RESOURCE_TYPE_DISK, "/some/big/disk/path", 0); impl->acquire_resource(VIR_LOCK_MANAGER_RESOURCE_TYPE_DISK, "/some/big/iso/file/path", VIR_LOCK_MANAGER_RESOURCE_READONLY); if (!(impl->startup_drv()) ...cannot obtain lock, so bail out... ...run QEMU... impl->shutdown_drv The thing here is that I have to translate the XML into something that the lock manager wants. Why not let me just pass the XML? Or the virDomainPtr? Rich. -- Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones New in Fedora 11: Fedora Windows cross-compiler. Compile Windows programs, test, and build Windows installers. Over 70 libraries supprt'd http://fedoraproject.org/wiki/MinGW http://www.annexia.org/fedora_mingw