repl5_replica_hash.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. /** BEGIN COPYRIGHT BLOCK
  2. * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
  3. * Copyright (C) 2005 Red Hat, Inc.
  4. * All rights reserved.
  5. *
  6. * License: GPL (version 3 or any later version).
  7. * See LICENSE for details.
  8. * END COPYRIGHT BLOCK **/
  9. #ifdef HAVE_CONFIG_H
  10. #include <config.h>
  11. #endif
  12. /* repl5_replica_hash.c */
  13. #include "repl5.h"
  14. #include "plhash.h"
  15. /* global data */
  16. static PLHashTable *s_hash;
  17. static Slapi_RWLock *s_lock;
  18. struct repl_enum_data
  19. {
  20. FNEnumReplica fn;
  21. void *arg;
  22. };
  23. /* Forward declarations */
  24. static PRIntn replica_destroy_hash_entry(PLHashEntry *he, PRIntn index, void *arg);
  25. static PRIntn replica_enumerate(PLHashEntry *he, PRIntn index, void *hash_data);
  26. int
  27. replica_init_name_hash()
  28. {
  29. /* allocate table */
  30. s_hash = PL_NewHashTable(0, PL_HashString, PL_CompareStrings,
  31. PL_CompareValues, NULL, NULL);
  32. if (s_hash == NULL) {
  33. slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name, "replica_init_name_hash: "
  34. "failed to allocate hash table; NSPR error - %d\n",
  35. PR_GetError());
  36. return -1;
  37. }
  38. /* create lock */
  39. s_lock = slapi_new_rwlock();
  40. if (s_lock == NULL) {
  41. slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name, "replica_init_name_hash: "
  42. "failed to create lock; NSPR error - %d\n",
  43. PR_GetError());
  44. replica_destroy_name_hash();
  45. return -1;
  46. }
  47. return 0;
  48. }
  49. void
  50. replica_destroy_name_hash()
  51. {
  52. /* destroy the content */
  53. PL_HashTableEnumerateEntries(s_hash, replica_destroy_hash_entry, NULL);
  54. if (s_hash)
  55. PL_HashTableDestroy(s_hash);
  56. if (s_lock)
  57. slapi_destroy_rwlock(s_lock);
  58. }
  59. int
  60. replica_add_by_name(const char *name, Object *replica)
  61. {
  62. if (name == NULL || replica == NULL) {
  63. slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name, "replica_add_by_name: NULL argument\n");
  64. return -1;
  65. }
  66. if (s_hash == NULL || s_lock == NULL) {
  67. slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name, "replica_add_by_name: "
  68. "replica hash is not initialized\n");
  69. return -1;
  70. }
  71. slapi_rwlock_wrlock(s_lock);
  72. /* make sure that the name is unique */
  73. if (PL_HashTableLookup(s_hash, name) != NULL) {
  74. slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name, "replica_add_by_name: "
  75. "replica with name (%s) already in the hash\n",
  76. name);
  77. slapi_rwlock_unlock(s_lock);
  78. return -1;
  79. }
  80. /* acquire replica object */
  81. object_acquire(replica);
  82. /* add replica */
  83. if (PL_HashTableAdd(s_hash, name, replica) == NULL) {
  84. slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name, "replica_add_by_name: "
  85. "failed to add replica with name (%s); NSPR error - %d\n",
  86. name, PR_GetError());
  87. object_release(replica);
  88. slapi_rwlock_unlock(s_lock);
  89. return -1;
  90. }
  91. slapi_rwlock_unlock(s_lock);
  92. return 0;
  93. }
  94. int
  95. replica_delete_by_name(const char *name)
  96. {
  97. Object *replica;
  98. if (name == NULL) {
  99. slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name, "replica_delete_by_name: "
  100. "NULL argument\n");
  101. return -1;
  102. }
  103. if (s_hash == NULL || s_lock == NULL) {
  104. slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name, "replica_delete_by_name: "
  105. "replica hash is not initialized\n");
  106. return -1;
  107. }
  108. slapi_rwlock_wrlock(s_lock);
  109. /* locate object */
  110. replica = (Object *)PL_HashTableLookup(s_hash, name);
  111. if (replica == NULL) {
  112. slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name, "replica_delete_by_name: "
  113. "replica with name (%s) is not in the hash.\n",
  114. name);
  115. slapi_rwlock_unlock(s_lock);
  116. return -1;
  117. }
  118. /* remove from hash */
  119. PL_HashTableRemove(s_hash, name);
  120. /* release replica */
  121. object_release(replica);
  122. slapi_rwlock_unlock(s_lock);
  123. return 0;
  124. }
  125. Object *
  126. replica_get_by_name(const char *name)
  127. {
  128. Object *replica;
  129. if (name == NULL) {
  130. slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name, "replica_get_by_name: "
  131. "NULL argument\n");
  132. return NULL;
  133. }
  134. if (s_hash == NULL || s_lock == NULL) {
  135. slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name, "replica_get_by_name: "
  136. "replica hash is not initialized\n");
  137. return NULL;
  138. }
  139. slapi_rwlock_rdlock(s_lock);
  140. /* locate object */
  141. replica = (Object *)PL_HashTableLookup(s_hash, name);
  142. if (replica == NULL) {
  143. slapi_rwlock_unlock(s_lock);
  144. return NULL;
  145. }
  146. object_acquire(replica);
  147. slapi_rwlock_unlock(s_lock);
  148. return replica;
  149. }
  150. void
  151. replica_enumerate_replicas(FNEnumReplica fn, void *arg)
  152. {
  153. struct repl_enum_data data;
  154. PR_ASSERT(fn);
  155. data.fn = fn;
  156. data.arg = arg;
  157. slapi_rwlock_wrlock(s_lock);
  158. PL_HashTableEnumerateEntries(s_hash, replica_enumerate, &data);
  159. slapi_rwlock_unlock(s_lock);
  160. }
  161. /* Helper functions */
  162. /* this function called for each hash node during hash destruction */
  163. static PRIntn
  164. replica_destroy_hash_entry(PLHashEntry *he, PRIntn index __attribute__((unused)), void *arg __attribute__((unused)))
  165. {
  166. Object *r_obj;
  167. Replica *r;
  168. if (he == NULL) {
  169. return HT_ENUMERATE_NEXT;
  170. }
  171. r_obj = (Object *)he->value;
  172. r = (Replica *)object_get_data(r_obj);
  173. PR_ASSERT(r);
  174. /* flash replica state to the disk */
  175. replica_flush(r);
  176. /* release replica object */
  177. object_release(r_obj);
  178. return HT_ENUMERATE_REMOVE;
  179. }
  180. static PRIntn
  181. replica_enumerate(PLHashEntry *he, PRIntn index __attribute__((unused)), void *hash_data)
  182. {
  183. Object *r_obj;
  184. Replica *r;
  185. struct repl_enum_data *data = hash_data;
  186. r_obj = (Object *)he->value;
  187. PR_ASSERT(r_obj);
  188. object_acquire(r_obj);
  189. r = (Replica *)object_get_data(r_obj);
  190. PR_ASSERT(r);
  191. data->fn(r, data->arg);
  192. object_release(r_obj);
  193. return HT_ENUMERATE_NEXT;
  194. }