repl5_agmt.c 46 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766
  1. /** BEGIN COPYRIGHT BLOCK
  2. * Copyright 2001 Sun Microsystems, Inc.
  3. * Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
  4. * All rights reserved.
  5. * END COPYRIGHT BLOCK **/
  6. /* repl5_agmt.c */
  7. /*
  8. Support for 5.0-style replication agreements.
  9. Directory Server 5.0 replication agreements contain information about
  10. replication consumers that we are supplying.
  11. This module encapsulates the methods available for adding, deleting,
  12. modifying, and firing replication agreements.
  13. Methods:
  14. agmt_new - Create a new replication agreement, in response to a new
  15. replication agreement being added over LDAP.
  16. agmt_delete - Destroy an agreement. It is an error to destroy an
  17. agreement that has not been stopped.
  18. agmt_getstatus - get the status of this replication agreement.
  19. agmt_replicate_now - initiate a replication session asap, even if the
  20. schedule says we shouldn't.
  21. agmt_start - start replicating, according to schedule. Starts a new
  22. thread to handle replication.
  23. agmt_stop - stop replicating asap and end replication thread.
  24. agmt_notify_change - notify the replication agreement about a change that
  25. has been logged. The replication agreement will
  26. decide if it needs to take some action, e.g. start a
  27. replication session.
  28. agmt_initialize_replica - start a complete replica refresh.
  29. agmt_set_schedule_from_entry - (re)set the schedule associated with this
  30. replication agreement based on a RA entry's contents.
  31. agmt_set_credentials_from_entry - (re)set the credentials used to bind
  32. to the remote replica.
  33. agmt_set_binddn_from_entry - (re)set the DN used to bind
  34. to the remote replica.
  35. agmt_set_bind_method_from_entry - (re)set the bind method used to bind
  36. to the remote replica (SIMPLE or SSLCLIENTAUTH).
  37. agmt_set_transportinfo_from_entry - (re)set the transport used to bind
  38. to the remote replica (SSL or not)
  39. */
  40. #include "repl5.h"
  41. #include "repl5_prot_private.h"
  42. #include "cl5_api.h"
  43. #define DEFAULT_TIMEOUT 600 /* (seconds) default outbound LDAP connection */
  44. #define TRANSPORT_FLAG_SSL 1
  45. #define STATUS_LEN 1024
  46. struct changecounter {
  47. ReplicaId rid;
  48. PRUint32 num_replayed;
  49. PRUint32 num_skipped;
  50. };
  51. typedef struct repl5agmt {
  52. char *hostname; /* remote hostname */
  53. int port; /* port of remote server */
  54. PRUint32 transport_flags; /* SSL, TLS, etc. */
  55. char *binddn; /* DN to bind as */
  56. struct berval *creds; /* Password, or certificate */
  57. int bindmethod; /* Bind method - simple, SSL */
  58. Slapi_DN *replarea; /* DN of replicated area */
  59. char **frac_attrs; /* list of fractional attributes to be replicated */
  60. Schedule *schedule; /* Scheduling information */
  61. int auto_initialize; /* 1 = automatically re-initialize replica */
  62. const Slapi_DN *dn; /* DN of replication agreement entry */
  63. const Slapi_RDN *rdn; /* RDN of replication agreement entry */
  64. char *long_name; /* Long name (rdn + host, port) of entry, for logging */
  65. Repl_Protocol *protocol; /* Protocol object - manages protocol */
  66. struct changecounter *changecounters[MAX_NUM_OF_MASTERS]; /* changes sent/skipped since server start up */
  67. int num_changecounters;
  68. time_t last_update_start_time; /* Local start time of last update session */
  69. time_t last_update_end_time; /* Local end time of last update session */
  70. char last_update_status[STATUS_LEN]; /* Status of last update. Format = numeric code <space> textual description */
  71. PRBool update_in_progress;
  72. time_t last_init_start_time; /* Local start time of last total init */
  73. time_t last_init_end_time; /* Local end time of last total init */
  74. char last_init_status[STATUS_LEN]; /* Status of last total init. Format = numeric code <space> textual description */
  75. PRLock *lock;
  76. Object *consumerRUV; /* last RUV received from the consumer - used for changelog purging */
  77. CSN *consumerSchemaCSN; /* last schema CSN received from the consumer */
  78. ReplicaId consumerRID; /* indicates if the consumer is the originator of a CSN */
  79. long timeout; /* timeout (in seconds) for outbound LDAP connections to remote server */
  80. PRBool stop_in_progress; /* set by agmt_stop when shutting down */
  81. long busywaittime; /* time in seconds to wait after getting a REPLICA BUSY from the consumer -
  82. to allow another supplier to finish sending its updates -
  83. if set to 0, this means to use the default value if we get a busy
  84. signal from the consumer */
  85. long pausetime; /* time in seconds to pause after sending updates -
  86. to allow another supplier to send its updates -
  87. should be greater than busywaittime -
  88. if set to 0, this means do not pause */
  89. } repl5agmt;
  90. /* Forward declarations */
  91. void agmt_delete(void **rap);
  92. static void update_window_state_change_callback (void *arg, PRBool opened);
  93. static int get_agmt_status(Slapi_PBlock *pb, Slapi_Entry* e,
  94. Slapi_Entry* entryAfter, int *returncode, char *returntext, void *arg);
  95. static int agmt_set_bind_method_no_lock(Repl_Agmt *ra, const Slapi_Entry *e);
  96. static int agmt_set_transportinfo_no_lock(Repl_Agmt *ra, const Slapi_Entry *e);
  97. /*
  98. Schema for replication agreement:
  99. cn
  100. nsds5ReplicaHost - hostname
  101. nsds5ReplicaPort - port number
  102. nsds5ReplicaTransportInfo - "SSL", "startTLS", or may be absent;
  103. nsds5ReplicaBindDN
  104. nsds5ReplicaCredentials
  105. nsds5ReplicaBindMethod - "SIMPLE" or "SSLCLIENTAUTH".
  106. nsds5ReplicaRoot - Replicated suffix
  107. nsds5ReplicatedAttributeList - Unused so far (meant for fractional repl).
  108. nsds5ReplicaUpdateSchedule
  109. nsds5ReplicaTimeout - Outbound repl operations timeout
  110. nsds50ruv - consumer's RUV
  111. nsds5ReplicaBusyWaitTime - time to wait after getting a REPLICA BUSY from the consumer
  112. nsds5ReplicaSessionPauseTime - time to pause after sending updates to allow another supplier to send
  113. */
  114. /*
  115. * Validate an agreement, making sure that it's valid.
  116. * Return 1 if the agreement is valid, 0 otherwise.
  117. */
  118. static int
  119. agmt_is_valid(Repl_Agmt *ra)
  120. {
  121. int return_value = 1; /* assume valid, initially */
  122. PR_ASSERT(NULL != ra);
  123. PR_ASSERT(NULL != ra->dn);
  124. if (NULL == ra->hostname)
  125. {
  126. slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "Replication agreement \"%s\" "
  127. "is malformed: missing host name.\n", slapi_sdn_get_dn(ra->dn));
  128. return_value = 0;
  129. }
  130. if (ra->port <= 0)
  131. {
  132. slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "Replication agreement \"%s\" "
  133. "is malformed: invalid port number %d.\n", slapi_sdn_get_dn(ra->dn), ra->port);
  134. return_value = 0;
  135. }
  136. if (ra->timeout < 0)
  137. {
  138. slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "Replication agreement \"%s\" "
  139. "is malformed: invalid timeout %d.\n", slapi_sdn_get_dn(ra->dn), ra->timeout);
  140. return_value = 0;
  141. }
  142. if (ra->busywaittime < 0)
  143. {
  144. slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "Replication agreement \"%s\" "
  145. "is malformed: invalid busy wait time %d.\n", slapi_sdn_get_dn(ra->dn), ra->busywaittime);
  146. return_value = 0;
  147. }
  148. if (ra->pausetime < 0)
  149. {
  150. slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "Replication agreement \"%s\" "
  151. "is malformed: invalid pausetime %d.\n", slapi_sdn_get_dn(ra->dn), ra->pausetime);
  152. return_value = 0;
  153. }
  154. return return_value;
  155. }
  156. Repl_Agmt *
  157. agmt_new_from_entry(Slapi_Entry *e)
  158. {
  159. Repl_Agmt *ra;
  160. char *tmpstr;
  161. Slapi_Attr *sattr;
  162. char *auto_initialize = NULL;
  163. char *val_nsds5BeginReplicaRefresh = "start";
  164. ra = (Repl_Agmt *)slapi_ch_calloc(1, sizeof(repl5agmt));
  165. if ((ra->lock = PR_NewLock()) == NULL)
  166. {
  167. slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "Unable to create new lock "
  168. "for replication agreement \"%s\" - agreement ignored.\n",
  169. slapi_entry_get_dn_const(e));
  170. goto loser;
  171. }
  172. /* Find all the stuff we need for the agreement */
  173. /* To Allow Consumer Initialisation when adding an agreement: */
  174. /*
  175. Using 'auto_initialize' member of 'repl5agmt' structure to
  176. store the effect of 'nsds5BeginReplicaRefresh' attribute's value
  177. in it.
  178. */
  179. auto_initialize = slapi_entry_attr_get_charptr(e, type_nsds5BeginReplicaRefresh);
  180. if ((auto_initialize != NULL) && (strcasecmp(auto_initialize, val_nsds5BeginReplicaRefresh) == 0))
  181. {
  182. ra->auto_initialize = STATE_PERFORMING_TOTAL_UPDATE;
  183. }
  184. else
  185. {
  186. ra->auto_initialize = STATE_PERFORMING_INCREMENTAL_UPDATE;
  187. }
  188. if (auto_initialize)
  189. {
  190. slapi_ch_free_string (&auto_initialize);
  191. }
  192. /* Host name of remote replica */
  193. ra->hostname = slapi_entry_attr_get_charptr(e, type_nsds5ReplicaHost);
  194. /* Port number for remote replica instance */
  195. ra->port = slapi_entry_attr_get_int(e, type_nsds5ReplicaPort);
  196. /* SSL, TLS, or other transport stuff */
  197. ra->transport_flags = 0;
  198. agmt_set_transportinfo_no_lock(ra, e);
  199. /* DN to use when binding. May be empty if cert-based auth is to be used. */
  200. ra->binddn = slapi_entry_attr_get_charptr(e, type_nsds5ReplicaBindDN);
  201. if (NULL == ra->binddn)
  202. {
  203. ra->binddn = slapi_ch_strdup("");
  204. }
  205. /* Credentials to use when binding. */
  206. ra->creds = (struct berval *)slapi_ch_malloc(sizeof(struct berval));
  207. ra->creds->bv_val = NULL;
  208. ra->creds->bv_len = 0;
  209. if (slapi_entry_attr_find(e, type_nsds5ReplicaCredentials, &sattr) == 0)
  210. {
  211. Slapi_Value *sval;
  212. if (slapi_attr_first_value(sattr, &sval) == 0)
  213. {
  214. const struct berval *bv = slapi_value_get_berval(sval);
  215. if (NULL != bv)
  216. {
  217. ra->creds->bv_val = slapi_ch_malloc(bv->bv_len + 1);
  218. memcpy(ra->creds->bv_val, bv->bv_val, bv->bv_len);
  219. ra->creds->bv_len = bv->bv_len;
  220. ra->creds->bv_val[bv->bv_len] = '\0'; /* be safe */
  221. }
  222. }
  223. }
  224. /* How to bind */
  225. (void)agmt_set_bind_method_no_lock(ra, e);
  226. /* timeout. */
  227. ra->timeout = DEFAULT_TIMEOUT;
  228. if (slapi_entry_attr_find(e, type_nsds5ReplicaTimeout, &sattr) == 0)
  229. {
  230. Slapi_Value *sval;
  231. if (slapi_attr_first_value(sattr, &sval) == 0)
  232. {
  233. ra->timeout = slapi_value_get_long(sval);
  234. }
  235. }
  236. /* DN of entry at root of replicated area */
  237. tmpstr = slapi_entry_attr_get_charptr(e, type_nsds5ReplicaRoot);
  238. if (NULL != tmpstr)
  239. {
  240. ra->replarea = slapi_sdn_new_dn_passin(tmpstr);
  241. }
  242. /* XXXggood get fractional attribute include/exclude lists here */
  243. /* Replication schedule */
  244. ra->schedule = schedule_new(update_window_state_change_callback, ra, agmt_get_long_name(ra));
  245. if (slapi_entry_attr_find(e, type_nsds5ReplicaUpdateSchedule, &sattr) == 0)
  246. {
  247. schedule_set(ra->schedule, sattr);
  248. }
  249. /* busy wait time - time to wait after getting REPLICA BUSY from consumer */
  250. ra->busywaittime = slapi_entry_attr_get_long(e, type_nsds5ReplicaBusyWaitTime);
  251. /* pause time - time to pause after a session has ended */
  252. ra->pausetime = slapi_entry_attr_get_long(e, type_nsds5ReplicaSessionPauseTime);
  253. /* consumer's RUV */
  254. if (slapi_entry_attr_find(e, type_ruvElement, &sattr) == 0)
  255. {
  256. RUV *ruv;
  257. if (ruv_init_from_slapi_attr(sattr, &ruv) == 0)
  258. {
  259. ra->consumerRUV = object_new (ruv, (FNFree)ruv_destroy);
  260. }
  261. }
  262. ra->consumerRID = 0;
  263. /* DN and RDN of the replication agreement entry itself */
  264. ra->dn = slapi_sdn_dup(slapi_entry_get_sdn((Slapi_Entry *)e));
  265. ra->rdn = slapi_rdn_new_sdn(ra->dn);
  266. /* Compute long name */
  267. {
  268. const char *agmtname = slapi_rdn_get_rdn(ra->rdn);
  269. char hostname[128];
  270. char *dot;
  271. strncpy(hostname, ra->hostname ? ra->hostname : "(unknown)", sizeof(hostname));
  272. hostname[sizeof(hostname)-1] = '\0';
  273. dot = strchr(hostname, '.');
  274. if (dot) {
  275. *dot = '\0';
  276. }
  277. ra->long_name = slapi_ch_malloc(strlen(agmtname) +
  278. strlen(hostname) + 25);
  279. sprintf(ra->long_name, "agmt=\"%s\" (%s:%d)", agmtname, hostname, ra->port);
  280. }
  281. /* Initialize status information */
  282. ra->last_update_start_time = 0UL;
  283. ra->last_update_end_time = 0UL;
  284. ra->num_changecounters = 0;
  285. ra->last_update_status[0] = '\0';
  286. ra->update_in_progress = PR_FALSE;
  287. ra->stop_in_progress = PR_FALSE;
  288. ra->last_init_end_time = 0UL;
  289. ra->last_init_start_time = 0UL;
  290. ra->last_init_status[0] = '\0';
  291. if (!agmt_is_valid(ra))
  292. {
  293. goto loser;
  294. }
  295. /* Now that the agreement is done, just check if changelog is configured */
  296. if (cl5GetState() != CL5_STATE_OPEN) {
  297. slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "WARNING: "
  298. "Replication agreement added but there is no changelog configured. "
  299. "No change will be replicated until a changelog is configured.\n");
  300. }
  301. /*
  302. * Establish a callback for this agreement's entry, so we can
  303. * adorn it with status information when read.
  304. */
  305. slapi_config_register_callback(SLAPI_OPERATION_SEARCH, DSE_FLAG_PREOP, slapi_sdn_get_ndn(ra->dn),
  306. LDAP_SCOPE_BASE, "(objectclass=*)", get_agmt_status, ra);
  307. return ra;
  308. loser:
  309. agmt_delete((void **)&ra);
  310. return NULL;
  311. }
  312. Repl_Agmt *
  313. agmt_new_from_pblock(Slapi_PBlock *pb)
  314. {
  315. Slapi_Entry *e;
  316. slapi_pblock_get(pb, SLAPI_ADD_ENTRY, &e);
  317. return agmt_new_from_entry(e);
  318. }
  319. /*
  320. This should never be called directly - only should be called
  321. as a destructor. XXXggood this is not finished
  322. */
  323. void
  324. agmt_delete(void **rap)
  325. {
  326. Repl_Agmt *ra;
  327. PR_ASSERT(NULL != rap);
  328. PR_ASSERT(NULL != *rap);
  329. ra = (Repl_Agmt *)*rap;
  330. /* do prot_delete first - we may be doing some processing using this
  331. replication agreement, and prot_delete will make sure the
  332. processing is complete - then it should be safe to clean up the
  333. other fields below
  334. */
  335. prot_delete(&ra->protocol);
  336. /*
  337. * Remove the callback for this agreement's entry
  338. */
  339. slapi_config_remove_callback(SLAPI_OPERATION_SEARCH, DSE_FLAG_PREOP,
  340. slapi_sdn_get_ndn(ra->dn),
  341. LDAP_SCOPE_BASE, "(objectclass=*)",
  342. get_agmt_status);
  343. /* slapi_ch_free accepts NULL pointer */
  344. slapi_ch_free((void **)&(ra->hostname));
  345. slapi_ch_free((void **)&(ra->binddn));
  346. if (NULL != ra->creds)
  347. {
  348. /* XXX free berval */
  349. }
  350. if (NULL != ra->replarea)
  351. {
  352. slapi_sdn_free(&ra->replarea);
  353. }
  354. if (NULL != ra->consumerRUV)
  355. {
  356. object_release (ra->consumerRUV);
  357. }
  358. csn_free (&ra->consumerSchemaCSN);
  359. while ( --(ra->num_changecounters) >= 0 )
  360. {
  361. slapi_ch_free((void **)&ra->changecounters[ra->num_changecounters]);
  362. }
  363. schedule_destroy(ra->schedule);
  364. slapi_ch_free((void **)&ra->long_name);
  365. slapi_ch_free((void **)rap);
  366. }
  367. /*
  368. * Allow replication for this replica to begin. Replication will
  369. * occur at the next scheduled time. Returns 0 on success, -1 on
  370. * failure.
  371. */
  372. int
  373. agmt_start(Repl_Agmt *ra)
  374. {
  375. Repl_Protocol *prot = NULL;
  376. int protocol_state;
  377. /* To Allow Consumer Initialisation when adding an agreement: */
  378. if (ra->auto_initialize == STATE_PERFORMING_TOTAL_UPDATE)
  379. {
  380. protocol_state = STATE_PERFORMING_TOTAL_UPDATE;
  381. }
  382. else
  383. {
  384. protocol_state = STATE_PERFORMING_INCREMENTAL_UPDATE;
  385. }
  386. /* First, create a new protocol object */
  387. if ((prot = prot_new(ra, protocol_state)) == NULL) {
  388. return -1;
  389. }
  390. /* Now it is safe to own the agreement lock */
  391. PR_Lock(ra->lock);
  392. /* Check that replication is not already started */
  393. if (ra->protocol != NULL) {
  394. slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "replication already started for agreement \"%s\"\n", agmt_get_long_name(ra));
  395. PR_Unlock(ra->lock);
  396. prot_free(&prot);
  397. return 0;
  398. }
  399. ra->protocol = prot;
  400. /* Start the protocol thread */
  401. prot_start(ra->protocol);
  402. PR_Unlock(ra->lock);
  403. return 0;
  404. }
  405. /*
  406. Cease replicating to this replica as soon as possible.
  407. */
  408. int
  409. agmt_stop(Repl_Agmt *ra)
  410. {
  411. int return_value = 0;
  412. Repl_Protocol *rp = NULL;
  413. PR_Lock(ra->lock);
  414. if (ra->stop_in_progress)
  415. {
  416. PR_Unlock(ra->lock);
  417. return return_value;
  418. }
  419. ra->stop_in_progress = PR_TRUE;
  420. rp = ra->protocol;
  421. PR_Unlock(ra->lock);
  422. if (NULL != rp) /* we use this pointer outside the lock - dangerous? */
  423. {
  424. prot_stop(rp);
  425. }
  426. PR_Lock(ra->lock);
  427. ra->stop_in_progress = PR_FALSE;
  428. /* we do not reuse the protocol object so free it */
  429. prot_free(&ra->protocol);
  430. PR_Unlock(ra->lock);
  431. return return_value;
  432. }
  433. /*
  434. Send any pending updates as soon as possible, ignoring any replication
  435. schedules.
  436. */
  437. int
  438. agmt_replicate_now(Repl_Agmt *ra)
  439. {
  440. int return_value = 0;
  441. return return_value;
  442. }
  443. /*
  444. * Return a copy of the remote replica's hostname.
  445. */
  446. char *
  447. agmt_get_hostname(const Repl_Agmt *ra)
  448. {
  449. char *return_value;
  450. PR_ASSERT(NULL != ra);
  451. PR_Lock(ra->lock);
  452. return_value = slapi_ch_strdup(ra->hostname);
  453. PR_Unlock(ra->lock);
  454. return return_value;
  455. }
  456. /*
  457. * Return the port number of the remote replica's instance.
  458. */
  459. int
  460. agmt_get_port(const Repl_Agmt *ra)
  461. {
  462. int return_value;
  463. PR_ASSERT(NULL != ra);
  464. PR_Lock(ra->lock);
  465. return_value = ra->port;
  466. PR_Unlock(ra->lock);
  467. return return_value;
  468. }
  469. /*
  470. * Return the transport flags for this agreement.
  471. */
  472. PRUint32
  473. agmt_get_transport_flags(const Repl_Agmt *ra)
  474. {
  475. unsigned int return_value;
  476. PR_ASSERT(NULL != ra);
  477. PR_Lock(ra->lock);
  478. return_value = ra->transport_flags;
  479. PR_Unlock(ra->lock);
  480. return return_value;
  481. }
  482. /*
  483. * Return a copy of the bind dn to be used with this
  484. * agreement (may return NULL if no binddn is required,
  485. * e.g. SSL client auth.
  486. */
  487. char *
  488. agmt_get_binddn(const Repl_Agmt *ra)
  489. {
  490. char *return_value;
  491. PR_ASSERT(NULL != ra);
  492. PR_Lock(ra->lock);
  493. return_value = ra->binddn == NULL ? NULL : slapi_ch_strdup(ra->binddn);
  494. PR_Unlock(ra->lock);
  495. return return_value;
  496. }
  497. /*
  498. * Return a copy of the credentials.
  499. */
  500. struct berval *
  501. agmt_get_credentials(const Repl_Agmt *ra)
  502. {
  503. struct berval *return_value;
  504. PR_ASSERT(NULL != ra);
  505. PR_Lock(ra->lock);
  506. return_value = (struct berval *)slapi_ch_malloc(sizeof(struct berval));
  507. return_value->bv_val = (char *)slapi_ch_malloc(ra->creds->bv_len + 1);
  508. return_value->bv_len = ra->creds->bv_len;
  509. memcpy(return_value->bv_val, ra->creds->bv_val, ra->creds->bv_len);
  510. return_value->bv_val[return_value->bv_len] = '\0'; /* just in case */
  511. PR_Unlock(ra->lock);
  512. return return_value;
  513. }
  514. int
  515. agmt_get_bindmethod(const Repl_Agmt *ra)
  516. {
  517. int return_value;
  518. PR_ASSERT(NULL != ra);
  519. PR_Lock(ra->lock);
  520. return_value = ra->bindmethod;
  521. PR_Unlock(ra->lock);
  522. return return_value;
  523. }
  524. /*
  525. * Return a copy of the dn at the top of the replicated area.
  526. */
  527. Slapi_DN *
  528. agmt_get_replarea(const Repl_Agmt *ra)
  529. {
  530. Slapi_DN *return_value;
  531. PR_ASSERT(NULL != ra);
  532. PR_Lock(ra->lock);
  533. return_value = slapi_sdn_new();
  534. slapi_sdn_copy(ra->replarea, return_value);
  535. PR_Unlock(ra->lock);
  536. return return_value;
  537. }
  538. int
  539. agmt_is_fractional(const Repl_Agmt *ra)
  540. {
  541. int return_value;
  542. PR_ASSERT(NULL != ra);
  543. PR_Lock(ra->lock);
  544. return_value = ra->frac_attrs != NULL;
  545. PR_Unlock(ra->lock);
  546. return return_value;
  547. }
  548. int
  549. agmt_is_fractional_attr(const Repl_Agmt *ra, const char *attrname)
  550. {
  551. int return_value;
  552. PR_ASSERT(NULL != ra);
  553. PR_Lock(ra->lock);
  554. return_value = 1; /* XXXggood finish this */
  555. PR_Unlock(ra->lock);
  556. return return_value;
  557. }
  558. int
  559. agmt_get_auto_initialize(const Repl_Agmt *ra)
  560. {
  561. int return_value;
  562. PR_ASSERT(NULL != ra);
  563. PR_Lock(ra->lock);
  564. return_value = ra->auto_initialize;
  565. PR_Unlock(ra->lock);
  566. return return_value;
  567. }
  568. long
  569. agmt_get_timeout(const Repl_Agmt *ra)
  570. {
  571. long return_value;
  572. PR_ASSERT(NULL != ra);
  573. PR_Lock(ra->lock);
  574. return_value = ra->timeout;
  575. PR_Unlock(ra->lock);
  576. return return_value;
  577. }
  578. long
  579. agmt_get_busywaittime(const Repl_Agmt *ra)
  580. {
  581. long return_value;
  582. PR_ASSERT(NULL != ra);
  583. PR_Lock(ra->lock);
  584. return_value = ra->busywaittime;
  585. PR_Unlock(ra->lock);
  586. return return_value;
  587. }
  588. long
  589. agmt_get_pausetime(const Repl_Agmt *ra)
  590. {
  591. long return_value;
  592. PR_ASSERT(NULL != ra);
  593. PR_Lock(ra->lock);
  594. return_value = ra->pausetime;
  595. PR_Unlock(ra->lock);
  596. return return_value;
  597. }
  598. /*
  599. * Warning - reference to the long name of the agreement is returned.
  600. * The long name of an agreement is the DN of the agreement entry,
  601. * followed by the host/port for the replica.
  602. */
  603. const char *
  604. agmt_get_long_name(const Repl_Agmt *ra)
  605. {
  606. char *return_value = NULL;
  607. return_value = ra ? ra->long_name : "";
  608. return return_value;
  609. }
  610. /*
  611. * Warning - reference to dn is returned. However, since the dn of
  612. * the replication agreement is its name, it won't change during the
  613. * lifetime of the replication agreement object.
  614. */
  615. const Slapi_DN *
  616. agmt_get_dn_byref(const Repl_Agmt *ra)
  617. {
  618. const Slapi_DN *return_value = NULL;
  619. PR_ASSERT(NULL != ra);
  620. if (NULL != ra)
  621. {
  622. return_value = ra->dn;
  623. }
  624. return return_value;
  625. }
  626. /* Return 1 if name matches the replication Dn, 0 otherwise */
  627. int
  628. agmt_matches_name(const Repl_Agmt *ra, const Slapi_DN *name)
  629. {
  630. int return_value = 0;
  631. PR_ASSERT(NULL != ra);
  632. if (NULL != ra)
  633. {
  634. PR_Lock(ra->lock);
  635. if (slapi_sdn_compare(name, ra->dn) == 0)
  636. {
  637. return_value = 1;
  638. }
  639. PR_Unlock(ra->lock);
  640. }
  641. return return_value;
  642. }
  643. /* Return 1 if name matches the replication area, 0 otherwise */
  644. int
  645. agmt_replarea_matches(const Repl_Agmt *ra, const Slapi_DN *name)
  646. {
  647. int return_value = 0;
  648. PR_ASSERT(NULL != ra);
  649. if (NULL != ra)
  650. {
  651. PR_Lock(ra->lock);
  652. if (slapi_sdn_compare(name, ra->replarea) == 0)
  653. {
  654. return_value = 1;
  655. }
  656. PR_Unlock(ra->lock);
  657. }
  658. return return_value;
  659. }
  660. int
  661. agmt_schedule_in_window_now(const Repl_Agmt *ra)
  662. {
  663. int return_value;
  664. PR_ASSERT(NULL != ra);
  665. PR_Lock(ra->lock);
  666. if (NULL != ra->schedule && schedule_in_window_now(ra->schedule))
  667. {
  668. return_value = 1;
  669. }
  670. else
  671. {
  672. return_value = 0;
  673. }
  674. PR_Unlock(ra->lock);
  675. return return_value;
  676. }
  677. /*
  678. * Set or reset the credentials used to bind to the remote replica.
  679. *
  680. * Returns 0 if credentials set, or -1 if an error occurred.
  681. */
  682. int
  683. agmt_set_credentials_from_entry(Repl_Agmt *ra, const Slapi_Entry *e)
  684. {
  685. Slapi_Attr *sattr = NULL;
  686. int return_value = 0;
  687. PR_ASSERT(NULL != ra);
  688. slapi_entry_attr_find(e, type_nsds5ReplicaCredentials, &sattr);
  689. PR_Lock(ra->lock);
  690. slapi_ch_free((void **)&ra->creds->bv_val);
  691. ra->creds->bv_len = 0;
  692. if (NULL != sattr)
  693. {
  694. Slapi_Value *sval = NULL;
  695. slapi_attr_first_value(sattr, &sval);
  696. if (NULL != sval)
  697. {
  698. const struct berval *bv = slapi_value_get_berval(sval);
  699. ra->creds->bv_val = slapi_ch_calloc(1, bv->bv_len + 1);
  700. memcpy(ra->creds->bv_val, bv->bv_val, bv->bv_len);
  701. ra->creds->bv_len = bv->bv_len;
  702. }
  703. }
  704. /* If no credentials set, set to zero-length string */
  705. ra->creds->bv_val = NULL == ra->creds->bv_val ? slapi_ch_strdup("") : ra->creds->bv_val;
  706. PR_Unlock(ra->lock);
  707. prot_notify_agmt_changed(ra->protocol, ra->long_name);
  708. return return_value;
  709. }
  710. /*
  711. * Set or reset the DN used to bind to the remote replica.
  712. *
  713. * Returns 0 if DN set, or -1 if an error occurred.
  714. */
  715. int
  716. agmt_set_binddn_from_entry(Repl_Agmt *ra, const Slapi_Entry *e)
  717. {
  718. Slapi_Attr *sattr = NULL;
  719. int return_value = 0;
  720. PR_ASSERT(NULL != ra);
  721. slapi_entry_attr_find(e, type_nsds5ReplicaBindDN, &sattr);
  722. PR_Lock(ra->lock);
  723. slapi_ch_free((void **)&ra->binddn);
  724. ra->binddn = NULL;
  725. if (NULL != sattr)
  726. {
  727. Slapi_Value *sval = NULL;
  728. slapi_attr_first_value(sattr, &sval);
  729. if (NULL != sval)
  730. {
  731. const char *val = slapi_value_get_string(sval);
  732. ra->binddn = strdup(val);
  733. }
  734. }
  735. /* If no BindDN set, set to zero-length string */
  736. if (ra->binddn == NULL) {
  737. ra->binddn = strdup("");
  738. }
  739. PR_Unlock(ra->lock);
  740. prot_notify_agmt_changed(ra->protocol, ra->long_name);
  741. return return_value;
  742. }
  743. /*
  744. * Set or reset the bind method used to bind to the remote replica.
  745. *
  746. * Returns 0 if bind method set, or -1 if an error occurred.
  747. */
  748. static int
  749. agmt_set_bind_method_no_lock(Repl_Agmt *ra, const Slapi_Entry *e)
  750. {
  751. char *tmpstr = NULL;
  752. int return_value = 0;
  753. PR_ASSERT(NULL != ra);
  754. tmpstr = slapi_entry_attr_get_charptr(e, type_nsds5ReplicaBindMethod);
  755. if (NULL == tmpstr || strcasecmp(tmpstr, "SIMPLE") == 0)
  756. {
  757. ra->bindmethod = BINDMETHOD_SIMPLE_AUTH;
  758. }
  759. else if (strcasecmp(tmpstr, "SSLCLIENTAUTH") == 0)
  760. {
  761. ra->bindmethod = BINDMETHOD_SSL_CLIENTAUTH;
  762. }
  763. else
  764. {
  765. ra->bindmethod = BINDMETHOD_SIMPLE_AUTH;
  766. }
  767. slapi_ch_free((void **)&tmpstr);
  768. return return_value;
  769. }
  770. int
  771. agmt_set_bind_method_from_entry(Repl_Agmt *ra, const Slapi_Entry *e)
  772. {
  773. char *tmpstr = NULL;
  774. int return_value = 0;
  775. PR_ASSERT(NULL != ra);
  776. PR_Lock(ra->lock);
  777. if (ra->stop_in_progress)
  778. {
  779. PR_Unlock(ra->lock);
  780. return return_value;
  781. }
  782. return_value = agmt_set_bind_method_no_lock(ra, e);
  783. PR_Unlock(ra->lock);
  784. prot_notify_agmt_changed(ra->protocol, ra->long_name);
  785. return return_value;
  786. }
  787. /*
  788. * Set or reset the transport used to bind to the remote replica.
  789. *
  790. * Returns 0 if transport set, or -1 if an error occurred.
  791. */
  792. static int
  793. agmt_set_transportinfo_no_lock(Repl_Agmt *ra, const Slapi_Entry *e)
  794. {
  795. char *tmpstr;
  796. int rc = 0;
  797. tmpstr = slapi_entry_attr_get_charptr(e, type_nsds5TransportInfo);
  798. if (NULL != tmpstr && strcasecmp(tmpstr, "SSL") == 0)
  799. {
  800. ra->transport_flags |= TRANSPORT_FLAG_SSL;
  801. } else {
  802. ra->transport_flags &= ~TRANSPORT_FLAG_SSL;
  803. }
  804. slapi_ch_free((void **)&tmpstr);
  805. return (rc);
  806. }
  807. int
  808. agmt_set_transportinfo_from_entry(Repl_Agmt *ra, const Slapi_Entry *e)
  809. {
  810. int return_value = 0;
  811. PR_ASSERT(NULL != ra);
  812. PR_Lock(ra->lock);
  813. if (ra->stop_in_progress)
  814. {
  815. PR_Unlock(ra->lock);
  816. return return_value;
  817. }
  818. return_value = agmt_set_transportinfo_no_lock(ra, e);
  819. PR_Unlock(ra->lock);
  820. prot_notify_agmt_changed(ra->protocol, ra->long_name);
  821. return return_value;
  822. }
  823. /*
  824. * Set or reset the replication schedule. Notify the protocol handler
  825. * that a change has been made.
  826. *
  827. * Returns 0 if schedule was set or -1 if an error occurred.
  828. */
  829. int
  830. agmt_set_schedule_from_entry( Repl_Agmt *ra, const Slapi_Entry *e )
  831. {
  832. Slapi_Attr *sattr;
  833. int return_value = 0;
  834. PR_ASSERT(NULL != ra);
  835. PR_Lock(ra->lock);
  836. if (ra->stop_in_progress)
  837. {
  838. PR_Unlock(ra->lock);
  839. return return_value;
  840. }
  841. PR_Unlock(ra->lock);
  842. if (slapi_entry_attr_find(e, type_nsds5ReplicaUpdateSchedule, &sattr) != 0)
  843. {
  844. sattr = NULL; /* no schedule ==> delete any existing one */
  845. }
  846. /* make it so */
  847. return_value = schedule_set(ra->schedule, sattr);
  848. if ( 0 == return_value ) {
  849. /* schedule set OK -- spread the news */
  850. prot_notify_agmt_changed(ra->protocol, ra->long_name);
  851. }
  852. return return_value;
  853. }
  854. /*
  855. * Set or reset the timeout used to bind to the remote replica.
  856. *
  857. * Returns 0 if timeout set, or -1 if an error occurred.
  858. */
  859. int
  860. agmt_set_timeout_from_entry(Repl_Agmt *ra, const Slapi_Entry *e)
  861. {
  862. Slapi_Attr *sattr = NULL;
  863. int return_value = -1;
  864. PR_ASSERT(NULL != ra);
  865. PR_Lock(ra->lock);
  866. if (ra->stop_in_progress)
  867. {
  868. PR_Unlock(ra->lock);
  869. return return_value;
  870. }
  871. slapi_entry_attr_find(e, type_nsds5ReplicaTimeout, &sattr);
  872. if (NULL != sattr)
  873. {
  874. Slapi_Value *sval = NULL;
  875. slapi_attr_first_value(sattr, &sval);
  876. if (NULL != sval)
  877. {
  878. long tmpval = slapi_value_get_long(sval);
  879. if (tmpval >= 0) {
  880. ra->timeout = tmpval;
  881. return_value = 0; /* success! */
  882. }
  883. }
  884. }
  885. PR_Unlock(ra->lock);
  886. if (return_value == 0)
  887. {
  888. prot_notify_agmt_changed(ra->protocol, ra->long_name);
  889. }
  890. return return_value;
  891. }
  892. /*
  893. * Set or reset the busywaittime
  894. *
  895. * Returns 0 if busywaittime set, or -1 if an error occurred.
  896. */
  897. int
  898. agmt_set_busywaittime_from_entry(Repl_Agmt *ra, const Slapi_Entry *e)
  899. {
  900. Slapi_Attr *sattr = NULL;
  901. int return_value = -1;
  902. PR_ASSERT(NULL != ra);
  903. PR_Lock(ra->lock);
  904. if (ra->stop_in_progress)
  905. {
  906. PR_Unlock(ra->lock);
  907. return return_value;
  908. }
  909. slapi_entry_attr_find(e, type_nsds5ReplicaBusyWaitTime, &sattr);
  910. if (NULL != sattr)
  911. {
  912. Slapi_Value *sval = NULL;
  913. slapi_attr_first_value(sattr, &sval);
  914. if (NULL != sval)
  915. {
  916. long tmpval = slapi_value_get_long(sval);
  917. if (tmpval >= 0) {
  918. ra->busywaittime = tmpval;
  919. return_value = 0; /* success! */
  920. }
  921. }
  922. }
  923. PR_Unlock(ra->lock);
  924. if (return_value == 0)
  925. {
  926. prot_notify_agmt_changed(ra->protocol, ra->long_name);
  927. }
  928. return return_value;
  929. }
  930. /*
  931. * Set or reset the pausetime
  932. *
  933. * Returns 0 if pausetime set, or -1 if an error occurred.
  934. */
  935. int
  936. agmt_set_pausetime_from_entry(Repl_Agmt *ra, const Slapi_Entry *e)
  937. {
  938. Slapi_Attr *sattr = NULL;
  939. int return_value = -1;
  940. PR_ASSERT(NULL != ra);
  941. PR_Lock(ra->lock);
  942. if (ra->stop_in_progress)
  943. {
  944. PR_Unlock(ra->lock);
  945. return return_value;
  946. }
  947. slapi_entry_attr_find(e, type_nsds5ReplicaSessionPauseTime, &sattr);
  948. if (NULL != sattr)
  949. {
  950. Slapi_Value *sval = NULL;
  951. slapi_attr_first_value(sattr, &sval);
  952. if (NULL != sval)
  953. {
  954. long tmpval = slapi_value_get_long(sval);
  955. if (tmpval >= 0) {
  956. ra->pausetime = tmpval;
  957. return_value = 0; /* success! */
  958. }
  959. }
  960. }
  961. PR_Unlock(ra->lock);
  962. if (return_value == 0)
  963. {
  964. prot_notify_agmt_changed(ra->protocol, ra->long_name);
  965. }
  966. return return_value;
  967. }
  968. /* XXXggood - also make this pass an arg that tells if there was
  969. * an update to a priority attribute */
  970. void
  971. agmt_notify_change(Repl_Agmt *agmt, Slapi_PBlock *pb)
  972. {
  973. if (NULL != pb)
  974. {
  975. /* Is the entry within our replicated area? */
  976. char *target_dn;
  977. Slapi_DN *target_sdn;
  978. int change_is_relevant = 0;
  979. PR_ASSERT(NULL != agmt);
  980. PR_Lock(agmt->lock);
  981. if (agmt->stop_in_progress)
  982. {
  983. PR_Unlock(agmt->lock);
  984. return;
  985. }
  986. slapi_pblock_get(pb, SLAPI_TARGET_DN, &target_dn);
  987. target_sdn = slapi_sdn_new_dn_byref(target_dn); /* XXX see if you can avoid allocating this */
  988. if (slapi_sdn_issuffix(target_sdn, agmt->replarea))
  989. {
  990. /*
  991. * Yep, it's in our replicated area. Is this a fractional
  992. * replication agreement?
  993. */
  994. if (NULL != agmt->frac_attrs)
  995. {
  996. /*
  997. * Yep, it's fractional. See if the change should be
  998. * tossed because it doesn't affect any of the replicated
  999. * attributes.
  1000. */
  1001. int optype;
  1002. int affects_fractional_attribute = 0;
  1003. slapi_pblock_get(pb, SLAPI_OPERATION_TYPE, &optype);
  1004. if (SLAPI_OPERATION_MODIFY == optype)
  1005. {
  1006. LDAPMod **mods;
  1007. int i, j;
  1008. slapi_pblock_get(pb, SLAPI_MODIFY_MODS, &mods);
  1009. for (i = 0; !affects_fractional_attribute && NULL != agmt->frac_attrs[i]; i++)
  1010. {
  1011. for (j = 0; !affects_fractional_attribute && NULL != mods[j]; j++)
  1012. {
  1013. if (slapi_attr_types_equivalent(agmt->frac_attrs[i],
  1014. mods[i]->mod_type))
  1015. {
  1016. affects_fractional_attribute = 1;
  1017. }
  1018. }
  1019. }
  1020. }
  1021. else
  1022. {
  1023. /*
  1024. * Add, delete, and modrdn always cause some sort of
  1025. * operation replay, even if agreement is fractional.
  1026. */
  1027. affects_fractional_attribute = 1;
  1028. }
  1029. if (affects_fractional_attribute)
  1030. {
  1031. change_is_relevant = 1;
  1032. }
  1033. }
  1034. else
  1035. {
  1036. /* Not a fractional agreement */
  1037. change_is_relevant = 1;
  1038. }
  1039. }
  1040. PR_Unlock(agmt->lock);
  1041. slapi_sdn_free(&target_sdn);
  1042. if (change_is_relevant)
  1043. {
  1044. /* Notify the protocol that a change has occurred */
  1045. prot_notify_update(agmt->protocol);
  1046. }
  1047. }
  1048. }
  1049. int
  1050. agmt_is_50_mm_protocol(const Repl_Agmt *agmt)
  1051. {
  1052. return 1; /* XXXggood could support > 1 protocol */
  1053. }
  1054. int
  1055. agmt_initialize_replica(const Repl_Agmt *agmt)
  1056. {
  1057. PR_ASSERT(NULL != agmt);
  1058. PR_Lock(agmt->lock);
  1059. if (agmt->stop_in_progress)
  1060. {
  1061. PR_Unlock(agmt->lock);
  1062. return 0;
  1063. }
  1064. PR_Unlock(agmt->lock);
  1065. /* Call prot_initialize_replica only if the suffix is enabled (agmt->protocol != NULL) */
  1066. if (NULL != agmt->protocol) {
  1067. prot_initialize_replica(agmt->protocol);
  1068. }
  1069. else {
  1070. /* agmt->protocol == NULL --> Suffix is disabled */
  1071. return -1;
  1072. }
  1073. return 0;
  1074. }
  1075. /* delete nsds5BeginReplicaRefresh attribute to indicate to the clients
  1076. that replica initialization have completed */
  1077. void
  1078. agmt_replica_init_done (const Repl_Agmt *agmt)
  1079. {
  1080. int rc;
  1081. Slapi_PBlock *pb = slapi_pblock_new ();
  1082. LDAPMod *mods [2];
  1083. LDAPMod mod;
  1084. mods[0] = &mod;
  1085. mods[1] = NULL;
  1086. mod.mod_op = LDAP_MOD_DELETE | LDAP_MOD_BVALUES;
  1087. mod.mod_type = (char*)type_nsds5ReplicaInitialize;
  1088. mod.mod_bvalues = NULL;
  1089. slapi_modify_internal_set_pb(pb, slapi_sdn_get_dn (agmt->dn), mods, NULL/* controls */,
  1090. NULL/* uniqueid */, repl_get_plugin_identity (PLUGIN_MULTIMASTER_REPLICATION), 0/* flags */);
  1091. slapi_modify_internal_pb (pb);
  1092. slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &rc);
  1093. if (rc != LDAP_SUCCESS && rc != LDAP_NO_SUCH_ATTRIBUTE)
  1094. {
  1095. slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "agmt_replica_init_done: "
  1096. "failed to remove (%s) attribute from (%s) entry; LDAP error - %d\n",
  1097. type_nsds5ReplicaInitialize, slapi_sdn_get_ndn (agmt->dn), rc);
  1098. }
  1099. slapi_pblock_destroy (pb);
  1100. }
  1101. /* Agreement object is acquired on behalf of the caller.
  1102. The caller is responsible for releasing the object
  1103. when it is no longer used */
  1104. Object*
  1105. agmt_get_consumer_ruv (Repl_Agmt *ra)
  1106. {
  1107. Object *rt = NULL;
  1108. PR_ASSERT(NULL != ra);
  1109. PR_Lock(ra->lock);
  1110. if (ra->consumerRUV)
  1111. {
  1112. object_acquire (ra->consumerRUV);
  1113. rt = ra->consumerRUV;
  1114. }
  1115. PR_Unlock(ra->lock);
  1116. return rt;
  1117. }
  1118. int
  1119. agmt_set_consumer_ruv (Repl_Agmt *ra, RUV *ruv)
  1120. {
  1121. if (ra == NULL || ruv == NULL)
  1122. {
  1123. slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "agmt_set_consumer_ruv: invalid argument"
  1124. " agmt - %p, ruv - %p\n", ra, ruv);
  1125. return -1;
  1126. }
  1127. PR_Lock(ra->lock);
  1128. if (ra->consumerRUV)
  1129. {
  1130. object_release (ra->consumerRUV);
  1131. }
  1132. ra->consumerRUV = object_new (ruv_dup (ruv), (FNFree)ruv_destroy);
  1133. PR_Unlock(ra->lock);
  1134. return 0;
  1135. }
  1136. void
  1137. agmt_update_consumer_ruv (Repl_Agmt *ra)
  1138. {
  1139. int rc;
  1140. RUV *ruv;
  1141. Slapi_Mod smod;
  1142. Slapi_Mod smod_last_modified;
  1143. Slapi_PBlock *pb;
  1144. LDAPMod *mods[3];
  1145. PR_ASSERT (ra);
  1146. PR_Lock(ra->lock);
  1147. if (ra->consumerRUV)
  1148. {
  1149. ruv = (RUV*) object_get_data (ra->consumerRUV);
  1150. PR_ASSERT (ruv);
  1151. ruv_to_smod(ruv, &smod);
  1152. ruv_last_modified_to_smod(ruv, &smod_last_modified);
  1153. /* it is ok to release the lock here because we are done with the agreement data.
  1154. we have to do it before issuing the modify operation because it causes
  1155. agmtlist_notify_all to be called which uses the same lock - hence the deadlock */
  1156. PR_Unlock(ra->lock);
  1157. pb = slapi_pblock_new ();
  1158. mods[0] = (LDAPMod *)slapi_mod_get_ldapmod_byref(&smod);
  1159. mods[1] = (LDAPMod *)slapi_mod_get_ldapmod_byref(&smod_last_modified);
  1160. mods[2] = NULL;
  1161. slapi_modify_internal_set_pb (pb, (char*)slapi_sdn_get_dn(ra->dn), mods, NULL, NULL,
  1162. repl_get_plugin_identity(PLUGIN_MULTIMASTER_REPLICATION), 0);
  1163. slapi_modify_internal_pb (pb);
  1164. slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &rc);
  1165. if (rc != LDAP_SUCCESS && rc != LDAP_NO_SUCH_ATTRIBUTE)
  1166. {
  1167. slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "%s: agmt_update_consumer_ruv: "
  1168. "failed to update consumer's RUV; LDAP error - %d\n",
  1169. ra->long_name, rc);
  1170. }
  1171. slapi_mod_done (&smod);
  1172. slapi_mod_done (&smod_last_modified);
  1173. slapi_pblock_destroy (pb);
  1174. }
  1175. else
  1176. PR_Unlock(ra->lock);
  1177. }
  1178. CSN*
  1179. agmt_get_consumer_schema_csn (Repl_Agmt *ra)
  1180. {
  1181. CSN *rt;
  1182. PR_ASSERT(NULL != ra);
  1183. PR_Lock(ra->lock);
  1184. rt = ra->consumerSchemaCSN;
  1185. PR_Unlock(ra->lock);
  1186. return rt;
  1187. }
  1188. void
  1189. agmt_set_consumer_schema_csn (Repl_Agmt *ra, CSN *csn)
  1190. {
  1191. PR_ASSERT(NULL != ra);
  1192. PR_Lock(ra->lock);
  1193. csn_free(&ra->consumerSchemaCSN);
  1194. ra->consumerSchemaCSN = csn;
  1195. PR_Unlock(ra->lock);
  1196. }
  1197. void
  1198. agmt_set_last_update_start (Repl_Agmt *ra, time_t start_time)
  1199. {
  1200. PR_ASSERT(NULL != ra);
  1201. if (NULL != ra)
  1202. {
  1203. ra->last_update_start_time = start_time;
  1204. ra->last_update_end_time = 0UL;
  1205. }
  1206. }
  1207. void
  1208. agmt_set_last_update_end (Repl_Agmt *ra, time_t end_time)
  1209. {
  1210. PR_ASSERT(NULL != ra);
  1211. if (NULL != ra)
  1212. {
  1213. ra->last_update_end_time = end_time;
  1214. }
  1215. }
  1216. void
  1217. agmt_set_last_init_start (Repl_Agmt *ra, time_t start_time)
  1218. {
  1219. PR_ASSERT(NULL != ra);
  1220. if (NULL != ra)
  1221. {
  1222. ra->last_init_start_time = start_time;
  1223. ra->last_init_end_time = 0UL;
  1224. }
  1225. }
  1226. void
  1227. agmt_set_last_init_end (Repl_Agmt *ra, time_t end_time)
  1228. {
  1229. PR_ASSERT(NULL != ra);
  1230. if (NULL != ra)
  1231. {
  1232. ra->last_init_end_time = end_time;
  1233. }
  1234. }
  1235. void
  1236. agmt_set_last_update_status (Repl_Agmt *ra, int ldaprc, int replrc, const char *message)
  1237. {
  1238. PR_ASSERT(NULL != ra);
  1239. if (NULL != ra)
  1240. {
  1241. if (replrc == NSDS50_REPL_UPTODATE)
  1242. {
  1243. /* no session started, no status update */
  1244. }
  1245. else if (ldaprc != LDAP_SUCCESS)
  1246. {
  1247. char *replmsg = NULL;
  1248. if ( replrc ) {
  1249. replmsg = protocol_response2string(replrc);
  1250. /* Do not mix the unknown replication error with the known ldap one */
  1251. if ( strcasecmp(replmsg, "unknown error") == 0 ) {
  1252. replmsg = NULL;
  1253. }
  1254. }
  1255. if (ldaprc > 0) {
  1256. PR_snprintf(ra->last_update_status, STATUS_LEN,
  1257. "%d %s%sLDAP error: %s%s%s",
  1258. ldaprc,
  1259. message?message:"",message?"":" - ",
  1260. ldap_err2string(ldaprc),
  1261. replmsg ? " - " : "", replmsg ? replmsg : "");
  1262. } else { /* ldaprc is < 0 */
  1263. PR_snprintf(ra->last_update_status, STATUS_LEN,
  1264. "%d %s%sSystem error%s%s",
  1265. ldaprc,message?message:"",message?"":" - ",
  1266. replmsg ? " - " : "", replmsg ? replmsg : "");
  1267. }
  1268. }
  1269. else if (replrc != 0)
  1270. {
  1271. if (replrc == NSDS50_REPL_REPLICA_READY)
  1272. {
  1273. PR_snprintf(ra->last_update_status, STATUS_LEN, "%d %s",
  1274. ldaprc, "Replica acquired successfully");
  1275. }
  1276. else if (replrc == NSDS50_REPL_REPLICA_BUSY)
  1277. {
  1278. PR_snprintf(ra->last_update_status, STATUS_LEN,
  1279. "%d Can't acquire busy replica", replrc );
  1280. }
  1281. else if (replrc == NSDS50_REPL_REPLICA_RELEASE_SUCCEEDED)
  1282. {
  1283. PR_snprintf(ra->last_update_status, STATUS_LEN, "%d %s",
  1284. ldaprc, "Replication session successful");
  1285. }
  1286. else if (replrc == NSDS50_REPL_DISABLED)
  1287. {
  1288. PR_snprintf(ra->last_update_status, STATUS_LEN, "%d Total update aborted: "
  1289. "Replication agreement for %s\n can not be updated while the replica is disabled.\n"
  1290. "(If the suffix is disabled you must enable it then restart the server for replication to take place).",
  1291. replrc, ra->long_name ? ra->long_name : "a replica");
  1292. /* Log into the errors log, as "ra->long_name" is not accessible from the caller */
  1293. slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
  1294. "Total update aborted: Replication agreement for \"%s\" "
  1295. "can not be updated while the replica is disabled\n", ra->long_name ? ra->long_name : "a replica");
  1296. slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
  1297. "(If the suffix is disabled you must enable it then restart the server for replication to take place).\n");
  1298. }
  1299. else
  1300. {
  1301. PR_snprintf(ra->last_update_status, STATUS_LEN,
  1302. "%d Replication error acquiring replica: %s%s%s",
  1303. replrc, protocol_response2string(replrc),
  1304. message?" - ":"",message?message:"");
  1305. }
  1306. }
  1307. else if (message != NULL)
  1308. {
  1309. PR_snprintf(ra->last_update_status, STATUS_LEN, "%d %s", ldaprc, message);
  1310. }
  1311. else { /* agmt_set_last_update_status(0,0,NULL) to reset agmt */
  1312. PR_snprintf(ra->last_update_status, STATUS_LEN, "%d", ldaprc);
  1313. }
  1314. }
  1315. }
  1316. void
  1317. agmt_set_last_init_status (Repl_Agmt *ra, int ldaprc, int replrc, const char *message)
  1318. {
  1319. PR_ASSERT(NULL != ra);
  1320. if (NULL != ra)
  1321. {
  1322. if (ldaprc != LDAP_SUCCESS)
  1323. {
  1324. char *replmsg = NULL;
  1325. if ( replrc ) {
  1326. replmsg = protocol_response2string(replrc);
  1327. /* Do not mix the unknown replication error with the known ldap one */
  1328. if ( strcasecmp(replmsg, "unknown error") == 0 ) {
  1329. replmsg = NULL;
  1330. }
  1331. }
  1332. if (ldaprc > 0) {
  1333. PR_snprintf(ra->last_init_status, STATUS_LEN,
  1334. "%d %s%sLDAP error: %s%s%s",
  1335. ldaprc,
  1336. message?message:"",message?"":" - ",
  1337. ldap_err2string(ldaprc),
  1338. replmsg ? " - " : "", replmsg ? replmsg : "");
  1339. } else { /* ldaprc is < 0 */
  1340. PR_snprintf(ra->last_init_status, STATUS_LEN,
  1341. "%d %s%sSystem error%s%s",
  1342. ldaprc,message?message:"",message?"":" - ",
  1343. replmsg ? " - " : "", replmsg ? replmsg : "");
  1344. }
  1345. }
  1346. else if (replrc != 0)
  1347. {
  1348. if (replrc == NSDS50_REPL_REPLICA_READY)
  1349. {
  1350. PR_snprintf(ra->last_init_status, STATUS_LEN, "%d %s",
  1351. ldaprc, "Replica acquired successfully");
  1352. }
  1353. else if (replrc == NSDS50_REPL_REPLICA_RELEASE_SUCCEEDED)
  1354. {
  1355. PR_snprintf(ra->last_init_status, STATUS_LEN, "%d %s",
  1356. ldaprc, "Replication session successful");
  1357. }
  1358. else if (replrc == NSDS50_REPL_DISABLED)
  1359. {
  1360. PR_snprintf(ra->last_init_status, STATUS_LEN, "%d Total update aborted: "
  1361. "Replication agreement for %s\n can not be updated while the replica is disabled.\n"
  1362. "(If the suffix is disabled you must enable it then restart the server for replication to take place).",
  1363. replrc, ra->long_name ? ra->long_name : "a replica");
  1364. /* Log into the errors log, as "ra->long_name" is not accessible from the caller */
  1365. slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
  1366. "Total update aborted: Replication agreement for \"%s\" "
  1367. "can not be updated while the replica is disabled\n", ra->long_name ? ra->long_name : "a replica");
  1368. slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
  1369. "(If the suffix is disabled you must enable it then restart the server for replication to take place).\n");
  1370. }
  1371. else
  1372. {
  1373. PR_snprintf(ra->last_init_status, STATUS_LEN,
  1374. "%d Replication error acquiring replica: %s%s%s",
  1375. replrc, protocol_response2string(replrc),
  1376. message?" - ":"",message?message:"");
  1377. }
  1378. }
  1379. else if (message != NULL)
  1380. {
  1381. PR_snprintf(ra->last_init_status, STATUS_LEN, "%d %s", ldaprc, message);
  1382. }
  1383. else { /* agmt_set_last_init_status(0,0,NULL) to reset agmt */
  1384. PR_snprintf(ra->last_init_status, STATUS_LEN, "%d", ldaprc);
  1385. }
  1386. }
  1387. }
  1388. void
  1389. agmt_set_update_in_progress (Repl_Agmt *ra, PRBool in_progress)
  1390. {
  1391. PR_ASSERT(NULL != ra);
  1392. if (NULL != ra)
  1393. {
  1394. ra->update_in_progress = in_progress;
  1395. }
  1396. }
  1397. void
  1398. agmt_inc_last_update_changecount (Repl_Agmt *ra, ReplicaId rid, int skipped)
  1399. {
  1400. PR_ASSERT(NULL != ra);
  1401. if (NULL != ra)
  1402. {
  1403. int i;
  1404. for ( i = 0; i < ra->num_changecounters; i++ )
  1405. {
  1406. if ( ra->changecounters[i]->rid == rid )
  1407. break;
  1408. }
  1409. if ( i < ra->num_changecounters )
  1410. {
  1411. if ( skipped )
  1412. ra->changecounters[i]->num_skipped ++;
  1413. else
  1414. ra->changecounters[i]->num_replayed ++;
  1415. }
  1416. else
  1417. {
  1418. ra->num_changecounters ++;
  1419. ra->changecounters[i] = (struct changecounter*) slapi_ch_calloc(1, sizeof(struct changecounter));
  1420. ra->changecounters[i]->rid = rid;
  1421. if ( skipped )
  1422. ra->changecounters[i]->num_skipped = 1;
  1423. else
  1424. ra->changecounters[i]->num_replayed = 1;
  1425. }
  1426. }
  1427. }
  1428. void
  1429. agmt_get_changecount_string (Repl_Agmt *ra, char *buf, int bufsize)
  1430. {
  1431. char tmp_buf[32]; /* 5 digit RID, 10 digit each replayed and skipped */
  1432. int i;
  1433. int buflen = 0;
  1434. *buf = '\0';
  1435. if (NULL != ra)
  1436. {
  1437. for ( i = 0; i < ra->num_changecounters; i++ )
  1438. {
  1439. PR_snprintf (tmp_buf, sizeof(tmp_buf), "%u:%u/%u ",
  1440. ra->changecounters[i]->rid,
  1441. ra->changecounters[i]->num_replayed,
  1442. ra->changecounters[i]->num_skipped);
  1443. PR_snprintf (buf+buflen, bufsize-buflen, "%s", tmp_buf);
  1444. buflen += strlen (tmp_buf);
  1445. }
  1446. }
  1447. }
  1448. static int
  1449. get_agmt_status(Slapi_PBlock *pb, Slapi_Entry* e, Slapi_Entry* entryAfter,
  1450. int *returncode, char *returntext, void *arg)
  1451. {
  1452. char *time_tmp = NULL;
  1453. char changecount_string[BUFSIZ];
  1454. Repl_Agmt *ra = (Repl_Agmt *)arg;
  1455. PR_ASSERT(NULL != ra);
  1456. if (NULL != ra)
  1457. {
  1458. PRBool reapActive = PR_FALSE;
  1459. Slapi_DN *replarea_sdn = NULL;
  1460. Object *repl_obj = NULL;
  1461. replarea_sdn = agmt_get_replarea(ra);
  1462. repl_obj = replica_get_replica_from_dn(replarea_sdn);
  1463. slapi_sdn_free(&replarea_sdn);
  1464. if (repl_obj) {
  1465. Replica *replica = (Replica*)object_get_data (repl_obj);
  1466. reapActive = replica_get_tombstone_reap_active(replica);
  1467. object_release(repl_obj);
  1468. }
  1469. slapi_entry_attr_set_int(e, "nsds5replicaReapActive", (int)reapActive);
  1470. /* these values persist in the dse.ldif file, so we delete them
  1471. here to avoid multi valued attributes */
  1472. slapi_entry_attr_delete(e, "nsds5replicaLastUpdateStart");
  1473. slapi_entry_attr_delete(e, "nsds5replicaLastUpdateEnd");
  1474. slapi_entry_attr_delete(e, "nsds5replicaChangesSentSinceStartup");
  1475. slapi_entry_attr_delete(e, "nsds5replicaLastUpdateStatus");
  1476. slapi_entry_attr_delete(e, "nsds5replicaUpdateInProgress");
  1477. slapi_entry_attr_delete(e, "nsds5replicaLastInitStart");
  1478. slapi_entry_attr_delete(e, "nsds5replicaLastInitStatus");
  1479. slapi_entry_attr_delete(e, "nsds5replicaLastInitEnd");
  1480. /* now, add the real values (singly) */
  1481. if (ra->last_update_start_time == 0)
  1482. {
  1483. slapi_entry_add_string(e, "nsds5replicaLastUpdateStart", "0");
  1484. }
  1485. else
  1486. {
  1487. time_tmp = format_genTime(ra->last_update_start_time);
  1488. slapi_entry_add_string(e, "nsds5replicaLastUpdateStart", time_tmp);
  1489. slapi_ch_free((void **)&time_tmp);
  1490. }
  1491. if (ra->last_update_end_time == 0)
  1492. {
  1493. slapi_entry_add_string(e, "nsds5replicaLastUpdateEnd", "0");
  1494. }
  1495. else
  1496. {
  1497. time_tmp = format_genTime(ra->last_update_end_time);
  1498. slapi_entry_add_string(e, "nsds5replicaLastUpdateEnd", time_tmp);
  1499. slapi_ch_free((void **)&time_tmp);
  1500. }
  1501. agmt_get_changecount_string (ra, changecount_string, sizeof (changecount_string) );
  1502. slapi_entry_add_string(e, "nsds5replicaChangesSentSinceStartup", changecount_string);
  1503. if (ra->last_update_status[0] == '\0')
  1504. {
  1505. slapi_entry_add_string(e, "nsds5replicaLastUpdateStatus", "0 No replication sessions started since server startup");
  1506. }
  1507. else
  1508. {
  1509. slapi_entry_add_string(e, "nsds5replicaLastUpdateStatus", ra->last_update_status);
  1510. }
  1511. slapi_entry_add_string(e, "nsds5replicaUpdateInProgress", ra->update_in_progress ? "TRUE" : "FALSE");
  1512. if (ra->last_init_start_time == 0)
  1513. {
  1514. slapi_entry_add_string(e, "nsds5replicaLastInitStart", "0");
  1515. }
  1516. else
  1517. {
  1518. time_tmp = format_genTime(ra->last_init_start_time);
  1519. slapi_entry_add_string(e, "nsds5replicaLastInitStart", time_tmp);
  1520. slapi_ch_free((void **)&time_tmp);
  1521. }
  1522. if (ra->last_init_end_time == 0)
  1523. {
  1524. slapi_entry_add_string(e, "nsds5replicaLastInitEnd", "0");
  1525. }
  1526. else
  1527. {
  1528. time_tmp = format_genTime(ra->last_init_end_time);
  1529. slapi_entry_add_string(e, "nsds5replicaLastInitEnd", time_tmp);
  1530. slapi_ch_free((void **)&time_tmp);
  1531. }
  1532. if (ra->last_init_status[0] != '\0')
  1533. {
  1534. slapi_entry_add_string(e, "nsds5replicaLastInitStatus", ra->last_init_status);
  1535. }
  1536. }
  1537. return SLAPI_DSE_CALLBACK_OK;
  1538. }
  1539. static void
  1540. update_window_state_change_callback (void *arg, PRBool opened)
  1541. {
  1542. Repl_Agmt *agmt = (Repl_Agmt*)arg;
  1543. PR_ASSERT (agmt);
  1544. if (opened)
  1545. {
  1546. prot_notify_window_opened (agmt->protocol);
  1547. }
  1548. else
  1549. {
  1550. prot_notify_window_closed (agmt->protocol);
  1551. }
  1552. }
  1553. ReplicaId
  1554. agmt_get_consumer_rid ( Repl_Agmt *agmt, void *conn )
  1555. {
  1556. if ( agmt->consumerRID <= 0 ) {
  1557. char mapping_tree_node[512];
  1558. struct berval **bvals = NULL;
  1559. PR_snprintf ( mapping_tree_node,
  1560. sizeof (mapping_tree_node),
  1561. "cn=replica,cn=\"%s\",cn=mapping tree,cn=config",
  1562. slapi_sdn_get_dn (agmt->replarea) );
  1563. conn_read_entry_attribute ( conn, mapping_tree_node, "nsDS5ReplicaID", &bvals );
  1564. if ( NULL != bvals && NULL != bvals[0] ) {
  1565. char *ridstr = slapi_ch_malloc( bvals[0]->bv_len + 1 );
  1566. memcpy ( ridstr, bvals[0]->bv_val, bvals[0]->bv_len );
  1567. ridstr[bvals[0]->bv_len] = '\0';
  1568. agmt->consumerRID = atoi (ridstr);
  1569. slapi_ch_free ( (void**) &ridstr );
  1570. ber_bvecfree ( bvals );
  1571. }
  1572. }
  1573. return agmt->consumerRID;
  1574. }