ua_namespace.h 3.1 KB

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