repl_connext.c 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  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. /* repl_connext.c - replication extension to the Connection object
  13. */
  14. #include "repl.h"
  15. #include "repl5.h"
  16. /* ***** Supplier side ***** */
  17. /* NOT NEEDED YET */
  18. /* ***** Consumer side ***** */
  19. /* consumer connection extension constructor */
  20. void* consumer_connection_extension_constructor (void *object __attribute__((unused)), void *parent __attribute__((unused)))
  21. {
  22. consumer_connection_extension *ext = (consumer_connection_extension*) slapi_ch_malloc (sizeof (consumer_connection_extension));
  23. if (ext == NULL)
  24. {
  25. slapi_log_err(SLAPI_LOG_PLUGIN, repl_plugin_name, "consumer_connection_extension_constructor - "
  26. "Unable to create replication consumer connection extension - out of memory\n" );
  27. }
  28. else
  29. {
  30. ext->is_legacy_replication_dn= 0;
  31. ext->repl_protocol_version = REPL_PROTOCOL_UNKNOWN;
  32. ext->replica_acquired = NULL;
  33. ext->isreplicationsession= 0;
  34. ext->supplier_ruv = NULL;
  35. ext->connection = NULL;
  36. ext->in_use_opid = -1;
  37. ext->lock = PR_NewLock();
  38. if (NULL == ext->lock)
  39. {
  40. slapi_log_err(SLAPI_LOG_PLUGIN, repl_plugin_name, "consumer_connection_extension_constructor - "
  41. "Unable to create replication consumer connection extension lock - out of memory\n" );
  42. /* no need to go through the full destructor, but still need to free up this memory */
  43. slapi_ch_free((void **)&ext);
  44. ext = NULL;
  45. }
  46. }
  47. return ext;
  48. }
  49. /* consumer connection extension destructor */
  50. void consumer_connection_extension_destructor (void *ext, void *object __attribute__((unused)), void *parent __attribute__((unused)))
  51. {
  52. PRUint64 connid = 0;
  53. if (ext)
  54. {
  55. /* Check to see if this replication session has acquired
  56. * a replica. If so, release it here.
  57. */
  58. consumer_connection_extension *connext = (consumer_connection_extension *)ext;
  59. if (NULL != connext->replica_acquired)
  60. {
  61. Replica *r = object_get_data ((Object*)connext->replica_acquired);
  62. /* If a total update was in progress, abort it */
  63. if (REPL_PROTOCOL_50_TOTALUPDATE == connext->repl_protocol_version)
  64. {
  65. Slapi_PBlock *pb = slapi_pblock_new();
  66. const Slapi_DN *repl_root_sdn = replica_get_root(r);
  67. PR_ASSERT(NULL != repl_root_sdn);
  68. if (NULL != repl_root_sdn)
  69. {
  70. slapi_pblock_set(pb, SLAPI_CONNECTION, connext->connection);
  71. slapi_pblock_set(pb, SLAPI_TARGET_SDN, (void*)repl_root_sdn);
  72. slapi_pblock_get(pb, SLAPI_CONN_ID, &connid);
  73. slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name,
  74. "consumer_connection_extension_destructor - "
  75. "Aborting total update in progress for replicated "
  76. "area %s connid=%" PRIu64 "\n", slapi_sdn_get_dn(repl_root_sdn), connid);
  77. slapi_stop_bulk_import(pb);
  78. }
  79. else
  80. {
  81. slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name,
  82. "consumer_connection_extension_destructor - Can't determine root "
  83. "of replicated area.\n");
  84. }
  85. slapi_pblock_destroy(pb);
  86. /* allow reaping again */
  87. replica_set_tombstone_reap_stop(r, PR_FALSE);
  88. }
  89. replica_relinquish_exclusive_access(r, connid, -1);
  90. object_release ((Object*)connext->replica_acquired);
  91. connext->replica_acquired = NULL;
  92. }
  93. if (connext->supplier_ruv)
  94. {
  95. ruv_destroy ((RUV **)&connext->supplier_ruv);
  96. }
  97. if (connext->lock)
  98. {
  99. PR_DestroyLock(connext->lock);
  100. connext->lock = NULL;
  101. }
  102. connext->in_use_opid = -1;
  103. connext->connection = NULL;
  104. slapi_ch_free((void **)&ext);
  105. }
  106. }
  107. /* Obtain exclusive access to this connection extension.
  108. * Returns the consumer_connection_extension* if successful, else NULL.
  109. *
  110. * This is similar to obtaining exclusive access to the replica, but not identical.
  111. * For the connection extension, you only want to hold on to exclusive access as
  112. * long as it is being actively used to process an operation. Mainly that means
  113. * while processing either a 'start' or an 'end' extended operation. This makes
  114. * certain that if another 'start' or 'end' operation is received on the connection,
  115. * the ops will not trample on each other's state. As soon as you are done with
  116. * that single operation, it is time to relinquish the connection extension.
  117. * That differs from acquiring exclusive access to the replica, which is held over
  118. * after the 'start' operation and relinquished during the 'end' operation.
  119. */
  120. consumer_connection_extension*
  121. consumer_connection_extension_acquire_exclusive_access(void* conn, PRUint64 connid, int opid)
  122. {
  123. consumer_connection_extension* ret = NULL;
  124. /* step 1, grab the connext */
  125. consumer_connection_extension* connext = (consumer_connection_extension*)
  126. repl_con_get_ext(REPL_CON_EXT_CONN, conn);
  127. if (NULL != connext)
  128. {
  129. /* step 2, acquire its lock */
  130. PR_Lock(connext->lock);
  131. /* step 3, see if it is not in use, or in use by us */
  132. if (0 > connext->in_use_opid)
  133. {
  134. /* step 4, take it! */
  135. connext->in_use_opid = opid;
  136. ret = connext;
  137. slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name,
  138. "consumer_connection_extension_acquire_exclusive_access - "
  139. "conn=%" PRIu64 " op=%d Acquired consumer connection extension\n",
  140. connid, opid);
  141. }
  142. else if (opid == connext->in_use_opid)
  143. {
  144. ret = connext;
  145. slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name,
  146. "consumer_connection_extension_acquire_exclusive_access - "
  147. "conn=%" PRIu64 " op=%d Reacquired consumer connection extension\n",
  148. connid, opid);
  149. }
  150. else
  151. {
  152. slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name,
  153. "consumer_connection_extension_acquire_exclusive_access - "
  154. "conn=%" PRIu64 " op=%d Could not acquire consumer connection extension; it is in use by op=%d\n",
  155. connid, opid, connext->in_use_opid);
  156. }
  157. /* step 5, drop the lock */
  158. PR_Unlock(connext->lock);
  159. }
  160. else
  161. {
  162. slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name,
  163. "consumer_connection_extension_acquire_exclusive_access - "
  164. "conn=%" PRIu64 " op=%d Could not acquire consumer extension, it is NULL!\n",
  165. connid, opid);
  166. }
  167. return ret;
  168. }
  169. /* Relinquish exclusive access to this connection extension.
  170. * Returns 0 if exclusive access could NOT be relinquished, and non-zero if it was.
  171. * Specifically:
  172. * 1 if the extension was in use and was relinquished.
  173. * 2 if the extension was not in use to begin with.
  174. *
  175. * The extension will only be relinquished if it was first acquired by this op,
  176. * or if 'force' is TRUE. Do not use 'force' without a legitimate reason, such
  177. * as when destroying the parent connection.
  178. *
  179. * cf. consumer_connection_extension_acquire_exclusive_access() for details on how,
  180. * when, and why you would want to acquire and relinquish exclusive access.
  181. */
  182. int
  183. consumer_connection_extension_relinquish_exclusive_access(void* conn, PRUint64 connid, int opid, PRBool force)
  184. {
  185. int ret = 0;
  186. /* step 1, grab the connext */
  187. consumer_connection_extension* connext = (consumer_connection_extension*)
  188. repl_con_get_ext(REPL_CON_EXT_CONN, conn);
  189. if (NULL != connext)
  190. {
  191. /* step 2, acquire its lock */
  192. PR_Lock(connext->lock);
  193. /* step 3, see if it is in use */
  194. if (0 > connext->in_use_opid)
  195. {
  196. slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name,
  197. "consumer_connection_extension_relinquish_exclusive_access - "
  198. "conn=%" PRIu64 " op=%d Consumer connection extension is not in use\n",
  199. connid, opid);
  200. ret = 2;
  201. }
  202. else if (opid == connext->in_use_opid)
  203. {
  204. /* step 4, relinquish it (normal) */
  205. slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name,
  206. "consumer_connection_extension_relinquish_exclusive_access - "
  207. "conn=%" PRIu64 " op=%d Relinquishing consumer connection extension\n",
  208. connid, opid);
  209. connext->in_use_opid = -1;
  210. ret = 1;
  211. }
  212. else if (force)
  213. {
  214. /* step 4, relinquish it (forced) */
  215. slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name,
  216. "consumer_connection_extension_relinquish_exclusive_access - "
  217. "conn=%" PRIu64 " op=%d Forced to relinquish consumer connection extension held by op=%d\n",
  218. connid, opid, connext->in_use_opid);
  219. connext->in_use_opid = -1;
  220. ret = 1;
  221. }
  222. else
  223. {
  224. slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name,
  225. "consumer_connection_extension_relinquish_exclusive_access - "
  226. "conn=%" PRIu64 " op=%d Not relinquishing consumer connection extension, it is held by op=%d!\n",
  227. connid, opid, connext->in_use_opid);
  228. }
  229. /* step 5, drop the lock */
  230. PR_Unlock(connext->lock);
  231. }
  232. else
  233. {
  234. slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name,
  235. "consumer_connection_extension_relinquish_exclusive_access - "
  236. "conn=%" PRIu64 " op=%d Could not relinquish consumer extension, it is NULL!\n",
  237. connid, opid);
  238. }
  239. return ret;
  240. }