ua_namespace.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460
  1. #include "ua_namespace.h"
  2. #include <string.h>
  3. #include <stdio.h>
  4. UA_Int32 init_tc(transaction_context * tc) {
  5. return UA_list_init((UA_list_List*) tc);
  6. }
  7. /* The central data structure is a hash-map of UA_Node objects.
  8. Entry lookup via Algorithm D from Knuth's TAOCP (no linked lists here).
  9. Table of primes and mod-functions are from libiberty (licensed under LGPL) */
  10. struct prime_ent {
  11. hash_t prime;
  12. hash_t inv;
  13. hash_t inv_m2; /* inverse of prime-2 */
  14. hash_t shift;
  15. };
  16. static struct prime_ent const prime_tab[] = {
  17. { 7, 0x24924925, 0x9999999b, 2 },
  18. { 13, 0x3b13b13c, 0x745d1747, 3 },
  19. { 31, 0x08421085, 0x1a7b9612, 4 },
  20. { 61, 0x0c9714fc, 0x15b1e5f8, 5 },
  21. { 127, 0x02040811, 0x0624dd30, 6 },
  22. { 251, 0x05197f7e, 0x073260a5, 7 },
  23. { 509, 0x01824366, 0x02864fc8, 8 },
  24. { 1021, 0x00c0906d, 0x014191f7, 9 },
  25. { 2039, 0x0121456f, 0x0161e69e, 10 },
  26. { 4093, 0x00300902, 0x00501908, 11 },
  27. { 8191, 0x00080041, 0x00180241, 12 },
  28. { 16381, 0x000c0091, 0x00140191, 13 },
  29. { 32749, 0x002605a5, 0x002a06e6, 14 },
  30. { 65521, 0x000f00e2, 0x00110122, 15 },
  31. { 131071, 0x00008001, 0x00018003, 16 },
  32. { 262139, 0x00014002, 0x0001c004, 17 },
  33. { 524287, 0x00002001, 0x00006001, 18 },
  34. { 1048573, 0x00003001, 0x00005001, 19 },
  35. { 2097143, 0x00004801, 0x00005801, 20 },
  36. { 4194301, 0x00000c01, 0x00001401, 21 },
  37. { 8388593, 0x00001e01, 0x00002201, 22 },
  38. { 16777213, 0x00000301, 0x00000501, 23 },
  39. { 33554393, 0x00001381, 0x00001481, 24 },
  40. { 67108859, 0x00000141, 0x000001c1, 25 },
  41. { 134217689, 0x000004e1, 0x00000521, 26 },
  42. { 268435399, 0x00000391, 0x000003b1, 27 },
  43. { 536870909, 0x00000019, 0x00000029, 28 },
  44. { 1073741789, 0x0000008d, 0x00000095, 29 },
  45. { 2147483647, 0x00000003, 0x00000007, 30 },
  46. /* Avoid "decimal constant so large it is unsigned" for 4294967291. */
  47. { 0xfffffffb, 0x00000006, 0x00000008, 31 }
  48. };
  49. UA_Int32 create_ns(namespace **result, uint32_t size) {
  50. namespace *ns = UA_NULL;
  51. uint32_t sizePrimeIndex = higher_prime_index(size);
  52. size = prime_tab[sizePrimeIndex].prime;
  53. if (UA_alloc((void **)&ns, sizeof(namespace)) != UA_SUCCESS) return UA_ERR_NO_MEMORY;
  54. if (UA_alloc((void **)&ns->entries, sizeof(ns_entry) * size) != UA_SUCCESS) {
  55. UA_free(ns);
  56. return UA_ERR_NO_MEMORY;
  57. }
  58. /* set entries to zero
  59. ns->entries[i].lock = UA_NUll;
  60. ns->entries[i].node = UA_NULL; */
  61. memset(ns->entries, 0, size * sizeof(ns_entry));
  62. ns->size = size;
  63. ns->count = 0;
  64. ns->sizePrimeIndex = sizePrimeIndex;
  65. *result = ns;
  66. return UA_SUCCESS;
  67. }
  68. void empty_ns(namespace *ns) {
  69. clear_ns(ns);
  70. /* Downsize the table. */
  71. if (ns->size > 1024*1024 / sizeof (ns_entry)) {
  72. int nindex = higher_prime_index (1024 / sizeof (ns_entry));
  73. int nsize = prime_tab[nindex].prime;
  74. UA_free(ns->entries);
  75. UA_alloc((void **)&ns->entries, sizeof(ns_entry) * nsize); //FIXME: Check return value
  76. ns->size = nsize;
  77. ns->sizePrimeIndex = nindex;
  78. }
  79. }
  80. /* This function frees all memory allocated for a namespace */
  81. void delete_ns (namespace *ns) {
  82. clear_ns(ns);
  83. UA_free(ns->entries);
  84. UA_free(ns);
  85. }
  86. UA_Int32 insert_node(namespace *ns, UA_Node *node) {
  87. if(ns->size * 3 <= ns->count*4) {
  88. if(expand(ns) != UA_SUCCESS)
  89. return UA_ERROR;
  90. }
  91. hash_t h = hash(&node->nodeId);
  92. ns_entry *slot = find_empty_slot(ns, h);
  93. #ifdef MULTITHREADING
  94. if (UA_alloc((void **)&slot->lock, sizeof(pthread_rwlock_t)) != UA_SUCCESS)
  95. return UA_ERR_NO_MEMORY;
  96. pthread_rwlock_init((pthread_rwlock_t *)slot->lock, NULL);
  97. #endif
  98. slot->node = node;
  99. return UA_SUCCESS;
  100. }
  101. UA_Int32 get_node(namespace *ns, const UA_NodeId *nodeid, UA_Node ** const result, ns_lock ** lock) {
  102. ns_entry *slot;
  103. if(find_slot(ns, &slot, nodeid) != UA_SUCCESS) return UA_ERROR;
  104. #ifdef MULTITHREADING
  105. if(pthread_rwlock_rdlock((pthread_rwlock_t *)slot->lock) != 0) return UA_ERROR;
  106. *lock = slot->lock;
  107. #endif
  108. *result = slot->node;
  109. return UA_SUCCESS;
  110. }
  111. UA_Int32 get_writable_node(namespace *ns, const UA_NodeId *nodeid, UA_Node **result, ns_lock ** lock) {
  112. ns_entry *slot;
  113. if(find_slot(ns, &slot, nodeid) != UA_SUCCESS) return UA_ERROR;
  114. #ifdef MULTITHREADING
  115. if(pthread_rwlock_wrlock((pthread_rwlock_t *)slot->lock) != 0) return UA_ERROR;
  116. *lock = slot->lock;
  117. #endif
  118. *result = slot->node;
  119. return UA_SUCCESS;
  120. }
  121. #ifdef MULTITHREADING
  122. static inline void release_context_walker(void * lock) { pthread_rwlock_unlock(lock); }
  123. #endif
  124. UA_Int32 get_tc_node(namespace *ns, transaction_context *tc, const UA_NodeId *nodeid, UA_Node ** const result, ns_lock ** lock) {
  125. ns_entry *slot;
  126. if(find_slot(ns, &slot, nodeid) != UA_SUCCESS) return UA_ERROR;
  127. #ifdef MULTITHREADING
  128. if(pthread_rwlock_tryrdlock((pthread_rwlock_t *)slot->lock) != 0) {
  129. /* Transaction failed. Release all acquired locks and bail out. */
  130. UA_list_destroy((UA_list_List*) tc, release_context_walker);
  131. return UA_ERROR;
  132. }
  133. UA_list_addPayloadToBack((UA_list_List*) tc, slot->lock);
  134. *lock = slot->lock;
  135. #endif
  136. *result = slot->node;
  137. return UA_SUCCESS;
  138. }
  139. UA_Int32 get_tc_writable_node(namespace *ns, transaction_context *tc, const UA_NodeId *nodeid, UA_Node **result, ns_lock ** lock) {
  140. ns_entry *slot;
  141. if(find_slot(ns, &slot, nodeid) != UA_SUCCESS) return UA_ERROR;
  142. #ifdef MULTITHREADING
  143. if(pthread_rwlock_trywrlock((pthread_rwlock_t *)slot->lock) != 0) {
  144. /* Transaction failed. Release all acquired locks and bail out. */
  145. UA_list_destroy((UA_list_List*) tc, release_context_walker);
  146. return UA_ERROR;
  147. }
  148. UA_list_addPayloadToBack((UA_list_List*) tc, slot->lock);
  149. *lock = slot->lock;
  150. #endif
  151. *result = slot->node;
  152. return UA_SUCCESS;
  153. }
  154. void delete_node(namespace *ns, UA_NodeId *nodeid) {
  155. ns_entry *slot;
  156. if (find_slot(ns, &slot, nodeid) != UA_SUCCESS)
  157. return;
  158. clear_slot(ns, slot);
  159. /* Downsize the hashmap if it is very empty */
  160. if(ns->count*8 < ns->size && ns->size > 32)
  161. expand(ns);
  162. }
  163. /* Hashing inspired by code from from
  164. http://www.azillionmonkeys.com/qed/hash.html, licensed under the LGPL 2.1 */
  165. #undef get16bits
  166. #if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) || defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__)
  167. #define get16bits(d) (*((const uint16_t *) (d)))
  168. #endif
  169. #if !defined (get16bits)
  170. #define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8) +(uint32_t)(((const uint8_t *)(d))[0]) )
  171. #endif
  172. static hash_t hash_string (const UA_Byte * data, UA_Int32 len) {
  173. hash_t hash = len;
  174. hash_t tmp;
  175. int rem;
  176. if (len <= 0 || data == UA_NULL) return 0;
  177. rem = len & 3;
  178. len >>= 2;
  179. /* Main loop */
  180. for (;len > 0; len--) {
  181. hash += get16bits (data);
  182. tmp = (get16bits (data+2) << 11) ^ hash;
  183. hash = (hash << 16) ^ tmp;
  184. data += 2*sizeof (uint16_t);
  185. hash += hash >> 11;
  186. }
  187. /* Handle end cases */
  188. switch (rem) {
  189. case 3: hash += get16bits (data);
  190. hash ^= hash << 16;
  191. hash ^= ((signed char)data[sizeof (uint16_t)]) << 18;
  192. hash += hash >> 11;
  193. break;
  194. case 2: hash += get16bits (data);
  195. hash ^= hash << 11;
  196. hash += hash >> 17;
  197. break;
  198. case 1: hash += (signed char)*data;
  199. hash ^= hash << 10;
  200. hash += hash >> 1;
  201. break;
  202. }
  203. /* Force "avalanching" of final 127 bits */
  204. hash ^= hash << 3;
  205. hash += hash >> 5;
  206. hash ^= hash << 4;
  207. hash += hash >> 17;
  208. hash ^= hash << 25;
  209. hash += hash >> 6;
  210. return hash;
  211. }
  212. static hash_t hash(const UA_NodeId *n) {
  213. switch (n->encodingByte) {
  214. case UA_NODEIDTYPE_TWOBYTE:
  215. case UA_NODEIDTYPE_FOURBYTE:
  216. case UA_NODEIDTYPE_NUMERIC:
  217. return (n->identifier.numeric * 2654435761) % 2^32; // Knuth's multiplicative hashing
  218. case UA_NODEIDTYPE_STRING:
  219. return hash_string(n->identifier.string.data, n->identifier.string.length);
  220. case UA_NODEIDTYPE_GUID:
  221. return hash_string((UA_Byte*) &(n->identifier.guid), sizeof(UA_Guid));
  222. case UA_NODEIDTYPE_BYTESTRING:
  223. return hash_string((UA_Byte*) n->identifier.byteString.data, n->identifier.byteString.length);
  224. default:
  225. return 0;
  226. }
  227. }
  228. /* The following function returns an index into the above table of the nearest prime number which is greater than N, and near a power of two. */
  229. static unsigned int higher_prime_index (unsigned long n) {
  230. unsigned int low = 0;
  231. unsigned int high = sizeof(prime_tab) / sizeof(prime_tab[0]);
  232. while (low != high) {
  233. unsigned int mid = low + (high - low) / 2;
  234. if (n > prime_tab[mid].prime)
  235. low = mid + 1;
  236. else
  237. high = mid;
  238. }
  239. /* if (n > prime_tab[low].prime) */
  240. /* abort (); */
  241. return low;
  242. }
  243. /* Return X % Y. */
  244. static inline hash_t mod_1 (hash_t x, hash_t y, hash_t inv, int shift) {
  245. /* The multiplicative inverses computed above are for 32-bit types, and requires that we are able to compute a highpart multiply. */
  246. #ifdef UNSIGNED_64BIT_TYPE
  247. __extension__ typedef UNSIGNED_64BIT_TYPE ull;
  248. if (sizeof (hash_t) * CHAR_BIT <= 32) {
  249. hash_t t1, t2, t3, t4, q, r;
  250. t1 = ((ull)x * inv) >> 32;
  251. t2 = x - t1;
  252. t3 = t2 >> 1;
  253. t4 = t1 + t3;
  254. q = t4 >> shift;
  255. r = x - (q * y);
  256. return r;
  257. }
  258. #endif
  259. return x % y; /* Otherwise just use the native division routines. */
  260. }
  261. static inline hash_t mod (hash_t h, const namespace *ns) {
  262. const struct prime_ent *p = &prime_tab[ns->sizePrimeIndex];
  263. return mod_1 (h, p->prime, p->inv, p->shift);
  264. }
  265. static inline hash_t mod_m2 (hash_t h, const namespace *ns) {
  266. const struct prime_ent *p = &prime_tab[ns->sizePrimeIndex];
  267. return 1 + mod_1 (h, p->prime - 2, p->inv_m2, p->shift);
  268. }
  269. static inline void clear_slot(namespace *ns, ns_entry *slot) {
  270. if(slot->node == UA_NULL)
  271. return;
  272. #ifdef MULTITHREADING
  273. pthread_rwlock_wrlock((pthread_rwlock_t *) slot->lock); /* Get write lock. */
  274. #endif
  275. switch(slot->node->nodeClass) {
  276. case UA_NODECLASS_OBJECT:
  277. UA_ObjectNode_delete((UA_ObjectNode *) slot->node);
  278. break;
  279. case UA_NODECLASS_VARIABLE:
  280. UA_VariableNode_delete((UA_VariableNode *) slot->node);
  281. break;
  282. case UA_NODECLASS_METHOD:
  283. UA_MethodNode_delete((UA_MethodNode *) slot->node);
  284. break;
  285. case UA_NODECLASS_OBJECTTYPE:
  286. UA_ObjectTypeNode_delete((UA_ObjectTypeNode *) slot->node);
  287. break;
  288. case UA_NODECLASS_VARIABLETYPE:
  289. UA_VariableTypeNode_delete((UA_VariableTypeNode *) slot->node);
  290. break;
  291. case UA_NODECLASS_REFERENCETYPE:
  292. UA_ReferenceTypeNode_delete((UA_ReferenceTypeNode *) slot->node);
  293. break;
  294. case UA_NODECLASS_DATATYPE:
  295. UA_DataTypeNode_delete((UA_DataTypeNode *) slot->node);
  296. break;
  297. case UA_NODECLASS_VIEW:
  298. UA_ViewNode_delete((UA_ViewNode *) slot->node);
  299. break;
  300. default:
  301. break;
  302. }
  303. slot->node = UA_NULL;
  304. #ifdef MULTITHREADING
  305. pthread_rwlock_destroy((pthread_rwlock_t *)slot->lock);
  306. UA_free(slot->lock);
  307. #endif
  308. }
  309. /* Delete all entries */
  310. static void clear_ns(namespace *ns) {
  311. uint32_t size = ns->size;
  312. ns_entry *entries = ns->entries;
  313. for (uint32_t i = 0; i < size; i++)
  314. clear_slot(ns, &entries[i]);
  315. ns->count = 0;
  316. }
  317. static UA_Int32 find_slot (const namespace *ns, ns_entry **slot, const UA_NodeId *nodeid) {
  318. hash_t h = hash(nodeid);
  319. hash_t index, hash2;
  320. uint32_t size;
  321. ns_entry *entry;
  322. size = ns->size;
  323. index = mod(h, ns);
  324. entry = &ns->entries[index];
  325. if (entry == UA_NULL)
  326. return UA_ERROR;
  327. if (UA_NodeId_compare(&entry->node->nodeId, nodeid) == UA_EQUAL) {
  328. *slot = entry;
  329. return UA_SUCCESS;
  330. }
  331. hash2 = mod_m2(h, ns);
  332. for (;;) {
  333. index += hash2;
  334. if (index >= size)
  335. index -= size;
  336. entry = &ns->entries[index];
  337. if (entry == UA_NULL)
  338. return UA_ERROR;
  339. if (UA_NodeId_compare(&entry->node->nodeId, nodeid) == UA_EQUAL) {
  340. *slot = entry;
  341. return UA_SUCCESS;
  342. }
  343. }
  344. return UA_SUCCESS;
  345. }
  346. /* Always returns an empty slot. This is inevitable if the entries are not
  347. completely full. */
  348. static ns_entry * find_empty_slot(const namespace *ns, hash_t h) {
  349. hash_t index = mod(h, ns);
  350. uint32_t size = ns->size;
  351. ns_entry *slot = &ns->entries[index];
  352. if (slot->node == UA_NULL)
  353. return slot;
  354. hash_t hash2 = mod_m2(h, ns);
  355. for (;;) {
  356. index += hash2;
  357. if (index >= size)
  358. index -= size;
  359. slot = &ns->entries[index];
  360. if (slot->node == UA_NULL)
  361. return slot;
  362. }
  363. return UA_NULL;
  364. }
  365. /* The following function changes size of memory allocated for the entries and
  366. repeatedly inserts the table elements. The occupancy of the table after the
  367. call will be about 50%. Naturally the hash table must already exist. Remember
  368. also that the place of the table entries is changed. If memory allocation
  369. failures are allowed, this function will return zero, indicating that the
  370. table could not be expanded. If all goes well, it will return a non-zero
  371. value. */
  372. static UA_Int32 expand (namespace *ns) {
  373. ns_entry *nentries;
  374. int32_t nsize;
  375. uint32_t nindex;
  376. ns_entry *oentries = ns->entries;
  377. int32_t osize = ns->size;
  378. ns_entry *olimit = &oentries[osize];
  379. int32_t count = ns->count;
  380. /* Resize only when table after removal of unused elements is either too full or too empty. */
  381. if (count * 2 < osize && (count * 8 > osize || osize <= 32)) {
  382. return UA_SUCCESS;
  383. }
  384. nindex = higher_prime_index (count * 2);
  385. nsize = prime_tab[nindex].prime;
  386. if (UA_alloc((void **)&nentries, sizeof(ns_entry)*nsize) != UA_SUCCESS)
  387. return UA_ERR_NO_MEMORY;
  388. ns->entries = nentries;
  389. ns->size = nsize;
  390. ns->sizePrimeIndex = nindex;
  391. ns_entry *p = oentries;
  392. do {
  393. if (p->node != UA_NULL) {
  394. ns_entry *q = find_empty_slot(ns, hash(&p->node->nodeId));
  395. *q = *p;
  396. }
  397. p++;
  398. }
  399. while (p < olimit);
  400. UA_free(oentries);
  401. return UA_SUCCESS;
  402. }