windows_protocol_util.c 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  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. * END COPYRIGHT BLOCK **/
  6. /* repl5_protocol_util.c */
  7. /*
  8. Code common to both incremental and total protocols.
  9. */
  10. #include "repl5.h"
  11. // #include "windows_prot_private.h"
  12. #include "repl5_prot_private.h"
  13. #include "windowsrepl.h"
  14. int ruv_private_new( RUV **ruv, RUV *clone );
  15. /*
  16. * Acquire exclusive access to a replica. Send a start replication extended
  17. * operation to the replica. The response will contain a success code, and
  18. * optionally the replica's update vector if acquisition is successful.
  19. * This function returns one of the following:
  20. * ACQUIRE_SUCCESS - the replica was acquired, and we have exclusive update access
  21. * ACQUIRE_REPLICA_BUSY - another master was updating the replica
  22. * ACQUIRE_FATAL_ERROR - something bad happened, and it's not likely to improve
  23. * if we wait.
  24. * ACQUIRE_TRANSIENT_ERROR - something bad happened, but it's probably worth
  25. * another try after waiting a while.
  26. * If ACQUIRE_SUCCESS is returned, then ruv will point to the replica's update
  27. * vector. It's possible that the replica does something goofy and doesn't
  28. * return us an update vector, so be prepared for ruv to be NULL (but this is
  29. * an error).
  30. */
  31. int
  32. windows_acquire_replica(Private_Repl_Protocol *prp, RUV **ruv)
  33. {
  34. char * prot_oid = REPL_NSDS50_INCREMENTAL_PROTOCOL_OID; //xXX get rid of this
  35. int return_value = ACQUIRE_SUCCESS;
  36. ConnResult crc;
  37. Repl_Connection *conn;
  38. PR_ASSERT(prp);
  39. if (prp->replica_acquired) /* we already acquire replica */
  40. {
  41. slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name,
  42. "%s: Remote replica already acquired\n",
  43. agmt_get_long_name(prp->agmt));
  44. return_value = ACQUIRE_FATAL_ERROR;
  45. return ACQUIRE_SUCCESS;
  46. }
  47. //if (NULL != ruv)
  48. //{ ruv_destroy ( ruv ); }
  49. {
  50. Replica *replica;
  51. Object *supl_ruv_obj, *cons_ruv_obj;
  52. PRBool is_newer = PR_FALSE;
  53. RUV *r;
  54. if (prp->agmt)
  55. {
  56. cons_ruv_obj = agmt_get_consumer_ruv(prp->agmt);
  57. }
  58. object_acquire(prp->replica_object);
  59. replica = object_get_data(prp->replica_object);
  60. supl_ruv_obj = replica_get_ruv ( replica );
  61. /* make a copy of the existing RUV as a starting point
  62. XXX this is probably a not-so-elegant hack */
  63. slapi_log_error(SLAPI_LOG_REPL, NULL, "acquire_replica, supplier RUV:\n");
  64. if (supl_ruv_obj) {
  65. object_acquire(supl_ruv_obj);
  66. ruv_dump ((RUV*) object_get_data ( supl_ruv_obj ), "supplier", NULL);
  67. object_release(supl_ruv_obj);
  68. }else
  69. slapi_log_error(SLAPI_LOG_REPL, NULL, "acquire_replica, supplier RUV = null\n");
  70. slapi_log_error(SLAPI_LOG_REPL, NULL, "acquire_replica, consumer RUV:\n");
  71. if (cons_ruv_obj) {
  72. RUV* con;
  73. object_acquire(cons_ruv_obj);
  74. con = (RUV*) object_get_data ( cons_ruv_obj );
  75. ruv_dump (con,"consumer", NULL);
  76. object_release( cons_ruv_obj );
  77. }else
  78. slapi_log_error(SLAPI_LOG_REPL, NULL, "acquire_replica, consumer RUV = null\n");
  79. is_newer = ruv_is_newer ( supl_ruv_obj, cons_ruv_obj );
  80. /* This follows ruv_is_newer, since it's always newer if it's null */
  81. if (cons_ruv_obj == NULL)
  82. {
  83. RUV *s; // int rc;
  84. s = (RUV*) object_get_data ( replica_get_ruv ( replica ) );
  85. agmt_set_consumer_ruv(prp->agmt, s );
  86. object_release ( replica_get_ruv ( replica ) );
  87. cons_ruv_obj = agmt_get_consumer_ruv(prp->agmt);
  88. }
  89. r = (RUV*) object_get_data ( cons_ruv_obj);
  90. *ruv = r;
  91. if ( supl_ruv_obj ) object_release ( supl_ruv_obj );
  92. if ( cons_ruv_obj ) object_release ( cons_ruv_obj );
  93. object_release (prp->replica_object);
  94. replica = NULL;
  95. if (is_newer == PR_FALSE) {
  96. prp->last_acquire_response_code = NSDS50_REPL_UPTODATE;
  97. return ACQUIRE_CONSUMER_WAS_UPTODATE;
  98. }
  99. }
  100. prp->last_acquire_response_code = NSDS50_REPL_REPLICA_NO_RESPONSE;
  101. /* Get the connection */
  102. conn = prp->conn;
  103. crc = windows_conn_connect(conn);
  104. if (CONN_OPERATION_FAILED == crc)
  105. {
  106. return_value = ACQUIRE_TRANSIENT_ERROR;
  107. }
  108. else if (CONN_SSL_NOT_ENABLED == crc)
  109. {
  110. return_value = ACQUIRE_FATAL_ERROR;
  111. }
  112. else
  113. {
  114. /* we don't want the timer to go off in the middle of an operation */
  115. windows_conn_cancel_linger(conn);
  116. /* Does the remote replica support the dirsync protocol?
  117. if it update the conn object */
  118. windows_conn_replica_supports_dirsync(conn);
  119. if (CONN_NOT_CONNECTED == crc || CONN_OPERATION_FAILED == crc)
  120. {
  121. /* We don't know anything about the remote replica. Try again later. */
  122. return_value = ACQUIRE_TRANSIENT_ERROR;
  123. }
  124. else
  125. {
  126. /* Good to go. Start the protocol. */
  127. CSN *current_csn = NULL;
  128. Slapi_DN *replarea_sdn;
  129. /* Obtain a current CSN */
  130. replarea_sdn = agmt_get_replarea(prp->agmt);
  131. current_csn = get_current_csn(replarea_sdn);
  132. if (NULL != current_csn)
  133. {
  134. /* Save consumer's RUV in the replication agreement.
  135. It is used by the changelog trimming code */
  136. // if (ruv && *ruv) agmt_set_consumer_ruv (prp->agmt, *ruv); XXX deadlock?
  137. // XXX
  138. return_value = ACQUIRE_SUCCESS;
  139. }
  140. else
  141. {
  142. /* Couldn't get a current CSN */
  143. slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name,
  144. "%s: Unable to obtain current CSN. "
  145. "Replication is aborting.\n",
  146. agmt_get_long_name(prp->agmt));
  147. return_value = ACQUIRE_FATAL_ERROR;
  148. }
  149. slapi_sdn_free(&replarea_sdn);
  150. }
  151. }
  152. if (ACQUIRE_SUCCESS != return_value)
  153. {
  154. /* could not acquire the replica, so reinstate the linger timer, since this
  155. means we won't call release_replica, which also reinstates the timer */
  156. windows_conn_start_linger(conn);
  157. }
  158. else
  159. {
  160. /* replica successfully acquired */
  161. prp->replica_acquired = PR_TRUE;
  162. }
  163. return return_value;
  164. }
  165. void
  166. windows_release_replica(Private_Repl_Protocol *prp)
  167. {
  168. struct berval *retdata = NULL;
  169. char *retoid = NULL;
  170. struct berval *payload = NULL;
  171. Slapi_DN *replarea_sdn = NULL;
  172. PR_ASSERT(NULL != prp);
  173. PR_ASSERT(NULL != prp->conn);
  174. if (!prp->replica_acquired)
  175. return;
  176. windows_conn_start_linger(prp->conn);
  177. prp->replica_acquired = PR_FALSE;
  178. }