Rather than passing the next-to-use file descriptor set Id and the hash table for rembering the mappings of aliases to file descriptor sets around, encapsulate the two in a class. Signed-off-by: Stefan Berger --- v4->v5: - followed Daniel Berrange's comments - converted to virObject - provide virFdSetNew --- src/Makefile.am | 1 src/libvirt_private.syms | 10 ++ src/util/virfdset.c | 205 +++++++++++++++++++++++++++++++++++++++++++++++ src/util/virfdset.h | 112 +++++++++++++++++++++++++ 4 files changed, 328 insertions(+) Index: libvirt/src/util/virfdset.c =================================================================== --- /dev/null +++ libvirt/src/util/virfdset.c @@ -0,0 +1,205 @@ +/* + * virfdset.c: File descriptor set support + * + * Copyright (C) 2013 IBM Corporation + * + * 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 + * . + * + * Author: Stefan Berger + */ + +#include + +#include "virfdset.h" +#include "virobject.h" +#include "viralloc.h" +#include "virutil.h" +#include "virerror.h" +#include "virbuffer.h" + +#define VIR_FROM_THIS VIR_FROM_NONE + + +struct _virFdSet { + virObject object; + virHashTablePtr aliasToFdSet; + unsigned int nextfdset; +}; + +static virClassPtr virFdSetClass; +static void virFdSetDispose(void *obj); + +static int virFdSetOnceInit(void) +{ + if (!(virFdSetClass = virClassNew(virClassForObject(), + "virFdSet", + sizeof(virFdSet), + virFdSetDispose))) + return -1; + + return 0; +} + +VIR_ONCE_GLOBAL_INIT(virFdSet) + +static void virFdSetDispose(void *obj) +{ + virFdSetPtr fdset = obj; + + virHashFree(fdset->aliasToFdSet); +} + +static void virFdSetFreeIntPtr(void *payload, + const void *name ATTRIBUTE_UNUSED) +{ + VIR_FREE(payload); +} + +virFdSetPtr virFdSetNew(void) +{ + virFdSetPtr fdset; + + if (virFdSetInitialize() < 0) + return NULL; + + if (!(fdset = virObjectNew(virFdSetClass))) + return NULL; + + if (!(fdset->aliasToFdSet = virHashCreate(10, virFdSetFreeIntPtr))) { + virObjectUnref(fdset); + return NULL; + } + fdset->nextfdset = 1; + + return fdset; +} + +void virFdSetFree(virFdSetPtr fdset) +{ + virObjectUnref(fdset); +} + +void virFdSetReset(virFdSetPtr fdset) +{ + virHashRemoveAll(fdset->aliasToFdSet); + fdset->nextfdset = 1; +} + +void virFdSetRemoveAlias(virFdSetPtr fdset, const char *alias) +{ + virHashRemoveEntry(fdset->aliasToFdSet, alias); +} + +int virFdSetNextSet(virFdSetPtr fdset, const char *alias, + unsigned int *fdsetnum) +{ + int *num; + + if (VIR_ALLOC(num) < 0) { + virReportOOMError(); + return -1; + } + + *num = fdset->nextfdset; + + if (virHashAddEntry(fdset->aliasToFdSet, alias, num) < 0) { + VIR_FREE(num); + return -1; + } + + *fdsetnum = fdset->nextfdset++; + + return 0; +} + +static void virFdSetPrintAliasToFdSet(void *payload, + const void *name, + void *data) +{ + virBufferPtr buf = data; + + virBufferAsprintf(buf, " \n", + (char *)name, + *(unsigned int *)payload); +} + +void virFdSetFormatXML(virFdSetPtr fdset, virBufferPtr buf) +{ + virBufferAsprintf(buf, "\n"); + virHashForEach(fdset->aliasToFdSet, virFdSetPrintAliasToFdSet, buf); + virBufferAsprintf(buf, "\n"); +} + +int virFdSetParseXML(virFdSetPtr fdset, const char *xPath, + xmlXPathContextPtr ctxt) +{ + xmlNodePtr *nodes = NULL; + int n, i; + char *key = NULL; + char *val = NULL; + unsigned int *fdsetnum = NULL; + int ret = 0; + + virFdSetReset(fdset); + + if ((n = virXPathNodeSet(xPath, ctxt, &nodes)) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + "%s", _("failed to parse qemu file descriptor sets")); + goto error; + } + if (n > 0) { + for (i = 0 ; i < n ; i++) { + key = virXMLPropString(nodes[i], "alias"); + val = virXMLPropString(nodes[i], "fdset"); + if (key && val) { + if (VIR_ALLOC(fdsetnum) < 0) { + virReportOOMError(); + ret = -1; + goto error; + } + if (virStrToLong_ui(val, NULL, 10, fdsetnum) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("incorrect fdset '%s', expected positive" + "integer"), val); + VIR_FREE(fdsetnum); + ret = -1; + goto error; + } + + if (fdset->nextfdset <= *fdsetnum) + fdset->nextfdset = *fdsetnum + 1; + + if (virHashAddEntry(fdset->aliasToFdSet, key, fdsetnum) < 0) { + virReportOOMError(); + VIR_FREE(fdset); + ret = -1; + goto error; + } + } + VIR_FREE(key); + VIR_FREE(val); + } + } + +error: + if (ret < 0) + virFdSetReset(fdset); + + VIR_FREE(nodes); + VIR_FREE(key); + VIR_FREE(val); + + return ret; +} Index: libvirt/src/util/virfdset.h =================================================================== --- /dev/null +++ libvirt/src/util/virfdset.h @@ -0,0 +1,112 @@ +/* + * virfdset.h: File descriptor set support + * + * Copyright (C) 2013 IBM Corporation + * + * 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 + * . + * + * Author: Stefan Berger + */ +#ifndef __FDSET_H__ +# define __FDSET_H__ + +# include "internal.h" +# include "virbuffer.h" +# include "virxml.h" +# include "virhash.h" + +typedef struct _virFdSet virFdSet; +typedef virFdSet *virFdSetPtr; + + +/** + * virFdSetNew + * + * Create a new FdSet, + * Returns pointer to new FdSet on success, NULL if no memory was available. + */ +virFdSetPtr virFdSetNew(void) ATTRIBUTE_RETURN_CHECK; + +/** + * virFdSetFree + * @fdset : the FdSet to free + * + * Free the FdSet + */ +void virFdSetFree(virFdSetPtr fdset); + +/** + * virFdSetReset + * @fdset: fdset + * + * Reset the @fdset and forget about all mappings + * of aliases to file descriptor set data + */ +void virFdSetReset(virFdSetPtr fdset) + ATTRIBUTE_NONNULL(1); + +/** + * virFdSetRemoveAlias + * @fdset: the fdset + * @alias: the alias to remove + * + * Remove the given alias' mapping from @fdset + */ +void virFdSetRemoveAlias(virFdSetPtr fdset, const char *alias) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); + + +/** + * virFdSetNextSet + * @fdset: fdset + * @alias: device alias + * @fdset: pointer to unsigned int for storing the file descriptor set id + * + * Get the next file descriptor set number and store it with the given + * @alias. If successful, return the file descriptor set id in @fdsetnum. + * + * Returns 0 on success, -1 on failure. + */ +int virFdSetNextSet(virFdSetPtr fdset, const char *alias, + unsigned int *fdsetnum) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3) + ATTRIBUTE_RETURN_CHECK; + +/** + * virFdSetFormatXML + * @fdset: fdset + * @buf: virBufferPtr for writing into + * + * Write XML representation of the @fdset into the buffer @buf. + */ +void virFdSetFormatXML(virFdSetPtr fdset, virBufferPtr buf) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); + +/** + * virFdSetParseXML + * @fdset: fdset + * @xPath: xpath expression to find the @fdset's XML nodes + * @ctxt: xpath context + * + * Parse the fdset XML representation and collect the data into @fdset. + * + * Returns 0 on success, -1 on failure. + */ +int virFdSetParseXML(virFdSetPtr fdset, const char *xPath, + xmlXPathContextPtr ctxt) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3) + ATTRIBUTE_RETURN_CHECK; + +#endif Index: libvirt/src/Makefile.am =================================================================== --- libvirt.orig/src/Makefile.am +++ libvirt/src/Makefile.am @@ -70,6 +70,7 @@ UTIL_SOURCES = \ util/virerror.c util/virerror.h \ util/virevent.c util/virevent.h \ util/vireventpoll.c util/vireventpoll.h \ + util/virfdset.c util/virfdset.h \ util/virfile.c util/virfile.h \ util/virhash.c util/virhash.h \ util/virhashcode.c util/virhashcode.h \ Index: libvirt/src/libvirt_private.syms =================================================================== --- libvirt.orig/src/libvirt_private.syms +++ libvirt/src/libvirt_private.syms @@ -645,6 +645,16 @@ virFDStreamOpen; virFDStreamOpenFile; +# virfdset.h +virFdSetFormatXML; +virFdSetFree; +virFdSetNew; +virFdSetNextSet; +virFdSetParseXML; +virFdSetRemoveAlias; +virFdSetReset; + + # hash.h virHashAddEntry; virHashCreate;