int genders_handle_destroy(genders_t handle) { if (_genders_handle_error_check(handle) < 0) return -1; __list_destroy(handle->nodeslist); __list_destroy(handle->attrvalslist); __list_destroy(handle->attrslist); free(handle->valbuf); __hash_destroy(handle->node_index); __hash_destroy(handle->attr_index); __hash_destroy(handle->attrval_index); free(handle->attrval_index_attr); __list_destroy(handle->attrval_buflist); /* "clean" handle */ _initialize_handle_info(handle); handle->magic = ~GENDERS_MAGIC_NUM; /* ~0xdeadbeef == 0xlivebeef :-) */ handle->is_loaded = 0; handle->nodeslist = NULL; handle->attrvalslist = NULL; handle->attrslist = NULL; free(handle); return 0; }
/* * _genders_copy_attrvalslist * * Copy contents of the attrvalslist list into the handlecopy. * */ static int _genders_copy_attrvalslist(genders_t handle, genders_t handlecopy) { ListIterator attrvalslistitr = NULL; ListIterator attrvalsitr = NULL; genders_attrvals_container_t avc; genders_attrvals_container_t newavc = NULL; genders_attrval_t newav = NULL; int rv = -1; __list_iterator_create(attrvalslistitr, handle->attrvalslist); while ((avc = list_next(attrvalslistitr))) { genders_attrval_t av = NULL; __list_iterator_create(attrvalsitr, avc->attrvals); __xmalloc(newavc, genders_attrvals_container_t, sizeof(struct genders_attrvals_container)); __list_create(newavc->attrvals, _genders_list_free_genders_attrval); newavc->index = avc->index; while ((av = list_next(attrvalsitr))) { __xmalloc(newav, genders_attrval_t, sizeof(struct genders_attrval)); __xstrdup(newav->attr, av->attr); if (av->val) __xstrdup(newav->val, av->val); else newav->val = NULL; newav->val_contains_subst = av->val_contains_subst; __list_append(newavc->attrvals, newav); newav = NULL; } __list_append(handlecopy->attrvalslist, newavc); newavc = NULL; } rv = 0; cleanup: if (rv < 0) { if (newav) { free(newav->attr); free(newav->val); free(newav); } if (newavc) { __list_destroy(newavc->attrvals); free(newavc); } } __list_iterator_destroy(attrvalslistitr); __list_iterator_destroy(attrvalsitr); return rv; }
genders_t genders_handle_create(void) { genders_t handle = NULL; /* Don't use the wrapper here, no errnum to set */ if (!(handle = (genders_t)malloc(sizeof(struct genders)))) goto cleanup; _initialize_handle_info(handle); handle->nodeslist = NULL; handle->attrvalslist = NULL; handle->attrslist = NULL; handle->attrval_buflist = NULL; __list_create(handle->nodeslist, _genders_list_free_genders_node); __list_create(handle->attrvalslist, _genders_list_free_attrvallist); __list_create(handle->attrslist, free); /* node_index, attr_index created in genders_load_data. Valbuf * created in genders_load_data after maxvallen is calculated */ handle->errnum = GENDERS_ERR_SUCCESS; return handle; cleanup: if (handle) { __list_destroy(handle->nodeslist); __list_destroy(handle->attrvalslist); __list_destroy(handle->attrslist); free(handle); } return NULL; }
/* * _genders_copy_fill_node_index * * Add keys into the node_index * */ static int _genders_copy_fill_node_index(genders_t handle, genders_t handlecopy) { List l = NULL; ListIterator itr = NULL; genders_node_t n; int rv = -1; __list_iterator_create(itr, handlecopy->nodeslist); while ((n = list_next(itr))) __hash_insert(handlecopy->node_index, n->name, n); rv = 0; cleanup: if (rv < 0) __list_destroy(l); __list_iterator_destroy(itr); return rv; }
static void * lock_for_pool_create (struct _LOCK_FOR_POOL * pstGlue, struct _ERROR_HANDLER * pstError) { int err = SUCCESS; struct _MEM_POOL * pstPool = (struct _MEM_POOL *)pstGlue->pPool; pstGlue->poolLock = NULL; pstGlue->stLockList.pData = pstGlue->stLockList.pPacker = pstGlue->stLockList.pGlue = NULL; if (!__list_create(&pstGlue->stLockList.pData, LINKED_LIST_POINTER, NULL, NULL)) { pstError->handle_error (pstError->pHandler, err = FATAL_CREATION_ERROR, "Fatal error in creating list for locks"); goto error; } if (!__data_converter_create(&pstGlue->stLockList.pPacker, MEMORY_TO_MEMORY, "struct{string; void *;};", NULL)) { pstError->handle_error (pstError->pHandler, err = FATAL_CREATION_ERROR, "Fatal error in creating packer for locks"); goto error; } if (!__glue_create_packer_for_data_structure(&pstGlue->stLockList.pGlue, pstGlue->stLockList.pPacker, GLUE_PACKER_FOR_LIST_AUTO_FREE, pstGlue->stLockList.pData, NULL)) { pstError->handle_error (pstError->pHandler, err = FATAL_CREATION_ERROR, "Fatal error in creating glue for locks"); goto error; } if (!locked_pool_add_glue (pstPool, pstGlue)) { pstError->handle_error(pstError->pHandler, err = FATAL_CREATION_ERROR, "Failed to add lock glue for pool"); goto error; } pstGlue->mem_pool_malloc = pstPool->mem_pool_malloc; pstGlue->mem_pool_realloc = pstPool->mem_pool_realloc; pstGlue->mem_pool_free = pstPool->mem_pool_free; pstGlue->mem_pool_open = pstPool->mem_pool_open; pstGlue->mem_pool_close = pstPool->mem_pool_close; pstPool->mem_pool_malloc = locked_malloc; pstPool->mem_pool_realloc = locked_realloc; pstPool->mem_pool_free = locked_free; pstPool->mem_pool_open = locked_open; pstPool->mem_pool_close = locked_close; error: if (err) { if (pstGlue->stLockList.pGlue) __glue_destroy_packer_for_data_structure(pstGlue->stLockList.pGlue), pstGlue->stLockList.pGlue = NULL; if (pstGlue->stLockList.pData) __list_destroy(pstGlue->stLockList.pData), pstGlue->stLockList.pData = NULL; if (pstGlue->stLockList.pPacker) __data_converter_destroy(pstGlue->stLockList.pPacker), pstGlue->stLockList.pPacker = NULL; return NULL; } else { return pstGlue; } }
static void lock_for_pool_destroy (struct _LOCK_FOR_POOL * pstGlue) { struct _MEM_POOL * pstPool = (struct _MEM_POOL *)pstGlue->pPool; // Clean up for (__list_start_iterator(pstGlue->stLockList.pData, 0); __list_has_next(pstGlue->stLockList.pData);) { struct _MEM_LOCK * pstLock = (struct _MEM_LOCK *)__list_next(pstGlue->stLockList.pData, NULL, NULL); __semaphore_release(pstLock->pLockHandle); __semaphore_destroy(pstLock->pLockHandle); } unlock_mem_pool(pstGlue, true); // Restore the function pointers pstPool->mem_pool_malloc = pstGlue->mem_pool_malloc; pstPool->mem_pool_realloc = pstGlue->mem_pool_realloc; pstPool->mem_pool_free = pstGlue->mem_pool_free; pstPool->mem_pool_open = pstGlue->mem_pool_open; pstPool->mem_pool_close = pstGlue->mem_pool_close; locked_pool_remove_glue (pstPool); __glue_destroy_packer_for_data_structure(pstGlue->stLockList.pGlue), pstGlue->stLockList.pGlue = NULL; __list_destroy(pstGlue->stLockList.pData), pstGlue->stLockList.pData = NULL; __data_converter_destroy(pstGlue->stLockList.pPacker), pstGlue->stLockList.pPacker = NULL; }
/* * _genders_copy_nodeslist * * Copy contents of the nodeslist list into the handlecopy. * */ static int _genders_copy_nodeslist(genders_t handle, genders_t handlecopy) { ListIterator itr = NULL; genders_node_t n = NULL; genders_node_t newn = NULL; int rv = -1; __list_iterator_create(itr, handle->nodeslist); while ((n = list_next(itr))) { __xmalloc(newn, genders_node_t, sizeof(struct genders_node)); __xstrdup(newn->name, n->name); __list_create(newn->attrlist, NULL); newn->attrcount = n->attrcount; newn->attrlist_index_size = n->attrlist_index_size; __hash_create(newn->attrlist_index, newn->attrlist_index_size, (hash_key_f)hash_key_string, (hash_cmp_f)strcmp, NULL); __list_append(handlecopy->nodeslist, newn); newn = NULL; } rv = 0; cleanup: if (rv < 0) { if (newn) { free(newn->name); __list_destroy(newn->attrlist); __hash_destroy(newn->attrlist_index); free(newn); } } __list_iterator_destroy(itr); return rv; }
/* * _genders_copy_fill_attr_index * * Add keys into the attr_index * */ static int _genders_copy_fill_attr_index(genders_t handle, genders_t handlecopy) { List l = NULL; ListIterator itr = NULL; char *attr; int rv = -1; __list_iterator_create(itr, handlecopy->attrslist); while ((attr = list_next(itr))) { __list_create(l, NULL); __hash_insert(handlecopy->attr_index, attr, l); l = NULL; } rv = 0; cleanup: if (rv < 0) __list_destroy(l); __list_iterator_destroy(itr); return rv; }
int genders_parse(genders_t handle, const char *filename, FILE *stream) { int errcount, rv = -1; int debugnumattrs = 0; int debugmaxattrs = 0; int debugmaxnodelen = 0; int debugmaxattrlen = 0; int debugmaxvallen = 0; List debugnodeslist = NULL; List debugattrvalslist = NULL; List debugattrslist = NULL; hash_t debugnode_index = NULL; int debugnode_index_size = GENDERS_NODE_INDEX_INIT_SIZE; hash_t debugattr_index = NULL; int debugattr_index_size = GENDERS_ATTR_INDEX_INIT_SIZE; if (_genders_handle_error_check(handle) < 0) goto cleanup; if (!stream) stream = stderr; __list_create(debugnodeslist, _genders_list_free_genders_node); __list_create(debugattrvalslist, _genders_list_free_attrvallist); __list_create(debugattrslist, free); __hash_create(debugnode_index, debugnode_index_size, (hash_key_f)hash_key_string, (hash_cmp_f)strcmp, NULL); __hash_create(debugattr_index, debugattr_index_size, (hash_key_f)hash_key_string, (hash_cmp_f)strcmp, (hash_del_f)list_destroy); if ((errcount = _genders_open_and_parse(handle, filename, &debugnumattrs, &debugmaxattrs, &debugmaxnodelen, &debugmaxattrlen, &debugmaxvallen, debugnodeslist, debugattrvalslist, debugattrslist, &(debugnode_index), &(debugnode_index_size), &(debugattr_index), &(debugattr_index_size), 1, stream)) < 0) goto cleanup; rv = errcount; handle->errnum = GENDERS_ERR_SUCCESS; cleanup: __list_destroy(debugnodeslist); __list_destroy(debugattrvalslist); __list_destroy(debugattrslist); __hash_destroy(debugnode_index); __hash_destroy(debugattr_index); return rv; }
int genders_index_attrvals(genders_t handle, const char *attr) { ListIterator nodeslist_itr = NULL; List l = NULL; List attrval_buflist = NULL; genders_node_t n; char *valbuf = NULL; hash_t attrval_index = NULL; char *attrval_index_attr = NULL; int rv; if (_genders_loaded_handle_error_check(handle) < 0) return -1; if (!attr || !strlen(attr)) { handle->errnum = GENDERS_ERR_PARAMETERS; goto cleanup; } /* check if attr is legit */ if ((rv = genders_isattr(handle, attr)) < 0) goto cleanup; if (!rv) { handle->errnum = GENDERS_ERR_NOTFOUND; goto cleanup; } /* check if index already created */ if (handle->attrval_index && !strcmp(handle->attrval_index_attr, attr)) { handle->errnum = GENDERS_ERR_SUCCESS; return 0; } /* Nothing to index if there are no nodes */ if (!handle->numnodes) { handle->errnum = GENDERS_ERR_SUCCESS; return 0; } /* Max possible hash size is number of nodes, so pick upper boundary */ __hash_create(attrval_index, handle->numnodes, (hash_key_f)hash_key_string, (hash_cmp_f)strcmp, (hash_del_f)list_destroy); /* Create a List to store buffers for later freeing */ __list_create(attrval_buflist, free); __list_iterator_create(nodeslist_itr, handle->nodeslist); while ((n = list_next(nodeslist_itr))) { int subst_occurred = 0; genders_attrval_t av; if (_genders_find_attrval(handle, n, attr, NULL, &av) < 0) goto cleanup; if (av) { char *valptr; if (av->val) { if (_genders_get_valptr(handle, n, av, &valptr, &subst_occurred) < 0) goto cleanup; } else valptr = GENDERS_NOVALUE; if (!(l = hash_find(attrval_index, valptr))) { __list_create(l, NULL); /* If a substitution occurred, we cannot use the av->val * pointer as the key, b/c the key contains some nonsense * characters (i.e. %n). So we have to copy this buffer and * store it somewhere to be freed later. */ if (subst_occurred) { __xstrdup(valbuf, valptr); __list_append(attrval_buflist, valbuf); valptr = valbuf; valbuf = NULL; } __hash_insert(attrval_index, valptr, l); } __list_append(l, n); l = NULL; } } __xstrdup(attrval_index_attr, attr); /* Delete/free previous index */ __hash_destroy(handle->attrval_index); free(handle->attrval_index_attr); __list_destroy(handle->attrval_buflist); handle->attrval_index = NULL; handle->attrval_index_attr = NULL; handle->attrval_index = attrval_index; handle->attrval_index_attr = attrval_index_attr; handle->attrval_buflist = attrval_buflist; __list_iterator_destroy(nodeslist_itr); handle->errnum = GENDERS_ERR_SUCCESS; return 0; cleanup: __list_iterator_destroy(nodeslist_itr); __list_destroy(l); __hash_destroy(attrval_index); __list_destroy(attrval_buflist); free(attrval_index_attr); free(valbuf); return -1; }