Rather than passing the next-to-use file descriptor set Id and the hash table for remembering the mappings of aliases to file descriptor sets around, encapsulate the two in a class. Signed-off-by: Stefan Berger --- v6->v7: - followed Eric's & Corey's comments on v6 v5->v6: - following to changeset 2e5d7798df v4->v5: - followed Daniel Berrange's comments - converted to virObject - provide virFdSetNew --- src/Makefile.am | 1 src/libvirt_private.syms | 8 ++ src/util/virfdset.c | 179 +++++++++++++++++++++++++++++++++++++++++++++++ src/util/virfdset.h | 94 ++++++++++++++++++++++++ 4 files changed, 282 insertions(+) Index: libvirt/src/util/virfdset.c =================================================================== --- /dev/null +++ libvirt/src/util/virfdset.c @@ -0,0 +1,179 @@ +/* + * 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); +} + +virFdSetPtr virFdSetNew(void) +{ + virFdSetPtr fdset; + + if (virFdSetInitialize() < 0) + return NULL; + + if (!(fdset = virObjectNew(virFdSetClass))) + return NULL; + + if (!(fdset->aliasToFdSet = virHashCreate(10, NULL))) { + virObjectUnref(fdset); + return NULL; + } + fdset->nextfdset = 1; + + return fdset; +} + +static 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) +{ + if (virHashAddEntry(fdset->aliasToFdSet, alias, + (void *)(intptr_t)fdset->nextfdset) < 0) + 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)(intptr_t)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; + int ret = -1; + + virFdSetReset(fdset); + + if ((n = virXPathNodeSet(xPath, ctxt, &nodes)) < 0) { + /* nothing to parse is not an error */ + ret = 0; + goto cleanup; + } + + if (n > 0) { + for (i = 0 ; i < n ; i++) { + key = virXMLPropString(nodes[i], "alias"); + val = virXMLPropString(nodes[i], "fdset"); + if (key && val) { + if (virStrToLong_ui(val, NULL, 10, &fdsetnum) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("incorrect fdset '%s', expected positive" + "integer"), val); + goto cleanup; + } + + if (fdset->nextfdset <= fdsetnum) + fdset->nextfdset = fdsetnum + 1; + + if (virHashAddEntry(fdset->aliasToFdSet, key, + (void *)(intptr_t)&fdsetnum) < 0) { + virReportOOMError(); + goto cleanup; + } + } + VIR_FREE(key); + VIR_FREE(val); + } + } + + ret = 0; + +cleanup: + 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,94 @@ +/* + * 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; + +/** + * 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 + * @fdsetnum: 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 @@ -79,6 +79,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 @@ -650,6 +650,14 @@ virFDStreamOpen; virFDStreamOpenFile; +# virfdset.h +virFdSetFormatXML; +virFdSetNew; +virFdSetNextSet; +virFdSetParseXML; +virFdSetRemoveAlias; + + # hash.h virHashAddEntry; virHashCreate;