1
0

repl_connext.c 8.8 KB

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