UA_StatusCode UA_Nodestore_default_new(UA_Nodestore *ns) { /* Allocate and initialize the nodemap */ UA_NodeMap *nodemap = (UA_NodeMap*)UA_malloc(sizeof(UA_NodeMap)); if(!nodemap) return UA_STATUSCODE_BADOUTOFMEMORY; nodemap->sizePrimeIndex = higher_prime_index(UA_NODEMAP_MINSIZE); nodemap->size = primes[nodemap->sizePrimeIndex]; nodemap->count = 0; nodemap->entries = (UA_NodeMapEntry**) UA_calloc(nodemap->size, sizeof(UA_NodeMapEntry*)); if(!nodemap->entries) { UA_free(nodemap); return UA_STATUSCODE_BADOUTOFMEMORY; } #ifdef UA_ENABLE_MULTITHREADING pthread_mutex_init(&nodemap->mutex, NULL); #endif /* Populate the nodestore */ ns->context = nodemap; ns->deleteNodestore = UA_NodeMap_delete; ns->inPlaceEditAllowed = true; ns->newNode = UA_NodeMap_newNode; ns->deleteNode = UA_NodeMap_deleteNode; ns->getNode = UA_NodeMap_getNode; ns->releaseNode = UA_NodeMap_releaseNode; ns->getNodeCopy = UA_NodeMap_getNodeCopy; ns->insertNode = UA_NodeMap_insertNode; ns->replaceNode = UA_NodeMap_replaceNode; ns->removeNode = UA_NodeMap_removeNode; ns->iterate = UA_NodeMap_iterate; return UA_STATUSCODE_GOOD; }
/* The occupancy of the table after the call will be about 50% */ static UA_StatusCode expand(UA_NodeStore *ns) { UA_UInt32 osize = ns->size; UA_UInt32 count = ns->count; /* Resize only when table after removal of unused elements is either too full or too empty */ if(count * 2 < osize && (count * 8 > osize || osize <= UA_NODESTORE_MINSIZE)) return UA_STATUSCODE_GOOD; UA_NodeStoreEntry **oentries = ns->entries; UA_UInt32 nindex = higher_prime_index(count * 2); UA_UInt32 nsize = primes[nindex]; UA_NodeStoreEntry **nentries; if(!(nentries = UA_calloc(nsize, sizeof(UA_NodeStoreEntry*)))) return UA_STATUSCODE_BADOUTOFMEMORY; ns->entries = nentries; ns->size = nsize; ns->sizePrimeIndex = nindex; /* recompute the position of every entry and insert the pointer */ for(size_t i = 0, j = 0; i < osize && j < count; i++) { if(!oentries[i]) continue; UA_NodeStoreEntry **e; containsNodeId(ns, &oentries[i]->node.nodeId, &e); /* We know this returns an empty entry here */ *e = oentries[i]; j++; } UA_free(oentries); return UA_STATUSCODE_GOOD; }
/* The occupancy of the table after the call will be about 50% */ static UA_StatusCode expand(UA_NodeMap *ns) { UA_UInt32 osize = ns->size; UA_UInt32 count = ns->count; /* Resize only when table after removal of unused elements is either too full or too empty */ if(count * 2 < osize && (count * 8 > osize || osize <= UA_NODEMAP_MINSIZE)) return UA_STATUSCODE_GOOD; UA_NodeMapEntry **oentries = ns->entries; UA_UInt32 nindex = higher_prime_index(count * 2); UA_UInt32 nsize = primes[nindex]; UA_NodeMapEntry **nentries = (UA_NodeMapEntry **)UA_calloc(nsize, sizeof(UA_NodeMapEntry*)); if(!nentries) return UA_STATUSCODE_BADOUTOFMEMORY; ns->entries = nentries; ns->size = nsize; ns->sizePrimeIndex = nindex; /* recompute the position of every entry and insert the pointer */ for(size_t i = 0, j = 0; i < osize && j < count; ++i) { if(oentries[i] <= UA_NODEMAP_TOMBSTONE) continue; UA_NodeMapEntry **e = findFreeSlot(ns, &oentries[i]->node.nodeId); UA_assert(e); *e = oentries[i]; ++j; } UA_free(oentries); return UA_STATUSCODE_GOOD; }
UA_NodeStore * UA_NodeStore_new(void) { UA_NodeStore *ns; if(!(ns = UA_malloc(sizeof(UA_NodeStore)))) return NULL; ns->sizePrimeIndex = higher_prime_index(UA_NODESTORE_MINSIZE); ns->size = primes[ns->sizePrimeIndex]; ns->count = 0; if(!(ns->entries = UA_calloc(ns->size, sizeof(UA_NodeStoreEntry*)))) { UA_free(ns); return NULL; } return ns; }