ua_namespace.h 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. #ifndef __NAMESPACE_H__
  2. #define __NAMESPACE_H__
  3. #include "ua_basictypes.h"
  4. #include "opcua.h"
  5. #include "ua_list.h"
  6. #ifdef MULTITHREADING
  7. #define _XOPEN_SOURCE 500
  8. #define __USE_UNIX98
  9. #include <pthread.h>
  10. typedef struct pthread_rwlock_t ns_lock;
  11. #else
  12. typedef void ns_lock;
  13. #endif
  14. /* Poor-man's transactions: If we need multiple locks and at least one of them
  15. is a writelock ("transaction"), a deadlock can be introduced in conjunction
  16. with a second thread.
  17. Convention: All nodes in a transaction (read and write) must be locked before
  18. the first write. If one write-lock cannot be acquired immediately, bail out
  19. and restart the transaction.
  20. A transaction_context is currently only a linked list of the acquired locks.
  21. More advanced transaction mechanisms will be established once the runtime
  22. behavior can be observed. */
  23. typedef UA_list_List transaction_context;
  24. UA_Int32 init_tc(transaction_context * tc);
  25. /* Each namespace is a hash-map of NodeIds to Nodes. Every entry in the hashmap
  26. consists of a pointer to a read-write lock and a pointer to the Node. */
  27. typedef struct ns_entry_t {
  28. #ifdef MULTITHREADING
  29. ns_lock *lock; /* locks are heap-allocated, so we can resize the entry-array online */
  30. #endif
  31. UA_Node *node;
  32. } ns_entry;
  33. typedef struct namespace_t {
  34. UA_Int32 namespaceId;
  35. UA_String namespaceUri;
  36. ns_entry *entries;
  37. uint32_t size;
  38. uint32_t count;
  39. uint32_t sizePrimeIndex; /* Current size, as an index into the table of primes. */
  40. } namespace;
  41. UA_Int32 create_ns(namespace **result, uint32_t size);
  42. void empty_ns(namespace *ns);
  43. void delete_ns(namespace *ns);
  44. UA_Int32 insert_node(namespace *ns, UA_Node *node);
  45. UA_Int32 get_node(namespace *ns, UA_NodeId *nodeid, UA_Node ** const result, ns_lock ** lock);
  46. UA_Int32 get_writable_node(namespace *ns, UA_NodeId *nodeid, UA_Node **result, ns_lock ** lock); // use only for _single_ writes.
  47. UA_Int32 get_tc_node(namespace *ns, transaction_context *tc, UA_NodeId *nodeid, UA_Node ** const result, ns_lock ** lock);
  48. UA_Int32 get_tc_writable_node(namespace *ns, transaction_context *tc, UA_NodeId *nodeid, UA_Node **result, ns_lock ** lock); // use only for _single_ writes.
  49. // inline void release_node(ns_lock *lock);
  50. // portable solution, see http://www.greenend.org.uk/rjk/tech/inline.html
  51. static inline void release_node(ns_lock *lock) {
  52. #ifdef MULTITHREADING
  53. pthread_rwlock_unlock((pthread_rwlock_t *)lock);
  54. #endif
  55. }
  56. void delete_node(namespace *ns, UA_NodeId *nodeid);
  57. /* Internal */
  58. typedef uint32_t hash_t;
  59. static hash_t hash_string(const UA_Byte * data, UA_Int32 len);
  60. static hash_t hash(const UA_NodeId *n);
  61. static unsigned int higher_prime_index (unsigned long n);
  62. static inline hash_t mod_1(hash_t x, hash_t y, hash_t inv, int shift);
  63. static inline hash_t mod(hash_t hash, const namespace *ns);
  64. static inline hash_t htab_mod_m2(hash_t hash, const namespace *ns);
  65. static inline void clear_slot(namespace *ns, ns_entry *slot);
  66. static void clear_ns(namespace *ns);
  67. static UA_Int32 find_slot(const namespace *ns, ns_entry **slot, UA_NodeId *nodeid);
  68. static ns_entry * find_empty_slot(const namespace *ns, hash_t hash);
  69. static UA_Int32 expand(namespace *ns);
  70. #endif /* __NAMESPACE_H */