windows_total.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727
  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. /*
  7. repl5_total.c - code that implements a total replica update.
  8. The requestValue of the NSDS50ReplicationEntry looks like this:
  9. requestValue ::= SEQUENCE {
  10. uniqueid OCTET STRING,
  11. dn LDAPDN,
  12. annotatedAttributes AnnotatedAttributeList
  13. }
  14. AnnotatedAttributeList ::= SET OF SEQUENCE {
  15. attributeType AttributeDescription,
  16. attributeDeletionCSN OCTET STRING OPTIONAL,
  17. attributeDeleted BOOLEAN DEFAULT FALSE,
  18. annotatedValues SET OF AnnotatedValue
  19. }
  20. AnnotatedValue ::= SEQUENCE {
  21. value AttributeValue,
  22. valueDeleted BOOLEAN DEFAULT FALSE,
  23. valueCSNSet SEQUENCE OF ValueCSN,
  24. }
  25. ValueCSN ::= SEQUENCE {
  26. CSNType ENUMERATED {
  27. valuePresenceCSN (1),
  28. valueDeletionCSN (2),
  29. valueDistinguishedCSN (3)
  30. }
  31. CSN OCTET STRING,
  32. }
  33. */
  34. #include "repl5.h"
  35. #include "windowsrepl.h"
  36. #define CSN_TYPE_VALUE_UPDATED_ON_WIRE 1
  37. #define CSN_TYPE_VALUE_DELETED_ON_WIRE 2
  38. #define CSN_TYPE_VALUE_DISTINGUISHED_ON_WIRE 3
  39. /* #define GORDONS_PATENTED_BER_DEBUG 1 */
  40. #ifdef GORDONS_PATENTED_BER_DEBUG
  41. #define BER_DEBUG(a) printf(a)
  42. #else
  43. #define BER_DEBUG(a)
  44. #endif
  45. /* Forward declarations */
  46. static int my_ber_printf_csn(BerElement *ber, const CSN *csn, const CSNType t);
  47. static int my_ber_printf_value(BerElement *ber, const char *type,
  48. const Slapi_Value *value, PRBool deleted);
  49. static int my_ber_printf_attr (BerElement *ber, Slapi_Attr *attr, PRBool deleted);
  50. static int my_ber_scanf_attr (BerElement *ber, Slapi_Attr **attr, PRBool *deleted);
  51. static int my_ber_scanf_value(BerElement *ber, Slapi_Value **value, PRBool *deleted);
  52. /*
  53. * Helper function - convert a CSN to a string and ber_printf() it.
  54. */
  55. static int
  56. my_ber_printf_csn(BerElement *ber, const CSN *csn, const CSNType t)
  57. {
  58. char csn_str[CSN_STRSIZE];
  59. unsigned long len;
  60. int rc = -1;
  61. int csn_type_as_ber = -1;
  62. switch (t)
  63. {
  64. case CSN_TYPE_VALUE_UPDATED:
  65. csn_type_as_ber = CSN_TYPE_VALUE_UPDATED_ON_WIRE;
  66. break;
  67. case CSN_TYPE_VALUE_DELETED:
  68. csn_type_as_ber = CSN_TYPE_VALUE_DELETED_ON_WIRE;
  69. break;
  70. case CSN_TYPE_VALUE_DISTINGUISHED:
  71. csn_type_as_ber = CSN_TYPE_VALUE_DISTINGUISHED_ON_WIRE;
  72. break;
  73. case CSN_TYPE_ATTRIBUTE_DELETED:
  74. break;
  75. default:
  76. slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name, "my_ber_printf_csn: unknown "
  77. "csn type %d encountered.\n", (int)t);
  78. return -1;
  79. }
  80. csn_as_string(csn,PR_FALSE,csn_str);
  81. /* we don't send type for attr csn since there is only one */
  82. if (t == CSN_TYPE_ATTRIBUTE_DELETED)
  83. {
  84. rc = ber_printf(ber, "s", csn_str);
  85. BER_DEBUG("s(csn_str)");
  86. }
  87. else
  88. {
  89. len = CSN_STRSIZE;
  90. rc = ber_printf(ber, "{es}", csn_type_as_ber, csn_str);
  91. BER_DEBUG("{e(csn type)s(csn)}");
  92. }
  93. return rc;
  94. }
  95. /*
  96. * Send a single annotated attribute value.
  97. */
  98. static int
  99. my_ber_printf_value(BerElement *ber, const char *type, const Slapi_Value *value, PRBool deleted)
  100. {
  101. const struct berval *bval = NULL;
  102. int rc = -1;
  103. const CSNSet *csnset;
  104. void *cookie;
  105. CSN *csn;
  106. CSNType t;
  107. bval = slapi_value_get_berval(value);
  108. BER_DEBUG("{o(value)");
  109. if (ber_printf(ber, "{o", bval->bv_val, bval->bv_len) == -1) /* Start sequence */
  110. {
  111. goto done;
  112. }
  113. /* if (ber_printf(ber, "o", bval->bv_val, bval->bv_len) == -1)
  114. {
  115. goto done;
  116. } */
  117. if (deleted)
  118. {
  119. BER_DEBUG("b(deleted flag)");
  120. if (ber_printf (ber, "b", PR_TRUE) == -1)
  121. {
  122. goto done;
  123. }
  124. }
  125. /* Send value CSN list */
  126. BER_DEBUG("{");
  127. if (ber_printf(ber, "{") == -1) /* Start set */
  128. {
  129. goto done;
  130. }
  131. /* Iterate over the sequence of CSNs. */
  132. csnset = value_get_csnset (value);
  133. if (csnset)
  134. {
  135. for (cookie = csnset_get_first_csn (csnset, &csn, &t); NULL != cookie;
  136. cookie = csnset_get_next_csn (csnset, cookie, &csn, &t))
  137. {
  138. /* Don't send any adcsns, since that was already sent */
  139. if (t != CSN_TYPE_ATTRIBUTE_DELETED)
  140. {
  141. if (my_ber_printf_csn(ber, csn, t) == -1)
  142. {
  143. goto done;
  144. }
  145. }
  146. }
  147. }
  148. BER_DEBUG("}");
  149. if (ber_printf(ber, "}") == -1) /* End CSN sequence */
  150. {
  151. goto done;
  152. }
  153. BER_DEBUG("}");
  154. if (ber_printf(ber, "}") == -1) /* End sequence */
  155. {
  156. goto done;
  157. }
  158. /* Everything's ok */
  159. rc = 0;
  160. done:
  161. return rc;
  162. }
  163. /* send a single attribute */
  164. static int
  165. my_ber_printf_attr (BerElement *ber, Slapi_Attr *attr, PRBool deleted)
  166. {
  167. Slapi_Value *value;
  168. char *type;
  169. int i;
  170. const CSN *csn;
  171. /* First, send the type */
  172. slapi_attr_get_type(attr, &type);
  173. BER_DEBUG("{s(type ");
  174. BER_DEBUG(type);
  175. BER_DEBUG(")");
  176. if (ber_printf(ber, "{s", type) == -1) /* Begin sequence for this type */
  177. {
  178. goto loser;
  179. }
  180. /* Send the attribute deletion CSN if present */
  181. csn = attr_get_deletion_csn(attr);
  182. if (csn)
  183. {
  184. if (my_ber_printf_csn(ber, csn, CSN_TYPE_ATTRIBUTE_DELETED) == -1)
  185. {
  186. goto loser;
  187. }
  188. }
  189. /* only send "is deleted" flag for deleted attributes since it defaults to false */
  190. if (deleted)
  191. {
  192. BER_DEBUG("b(del flag)");
  193. if (ber_printf (ber, "b", PR_TRUE) == -1)
  194. {
  195. goto loser;
  196. }
  197. }
  198. /*
  199. * Iterate through all the values.
  200. */
  201. BER_DEBUG("[");
  202. if (ber_printf(ber, "[") == -1) /* Begin set */
  203. {
  204. goto loser;
  205. }
  206. /*
  207. * Process the non-deleted values first.
  208. */
  209. i = slapi_attr_first_value(attr, &value);
  210. while (i != -1)
  211. {
  212. if (my_ber_printf_value(ber, type, value, PR_FALSE) == -1)
  213. {
  214. goto loser;
  215. }
  216. i= slapi_attr_next_value(attr, i, &value);
  217. }
  218. /*
  219. * Now iterate over all of the deleted values.
  220. */
  221. i= attr_first_deleted_value(attr, &value);
  222. while (i != -1)
  223. {
  224. if (my_ber_printf_value(ber, type, value, PR_TRUE) == -1)
  225. {
  226. goto loser;
  227. }
  228. i= attr_next_deleted_value(attr, i, &value);
  229. }
  230. BER_DEBUG("]");
  231. if (ber_printf(ber, "]") == -1) /* End set */
  232. {
  233. goto loser;
  234. }
  235. BER_DEBUG("}");
  236. if (ber_printf(ber, "}") == -1) /* End sequence for this type */
  237. {
  238. goto loser;
  239. }
  240. return 0;
  241. loser:
  242. return -1;
  243. }
  244. /*
  245. * Get an annotated value from the BerElement. Returns 0 on
  246. * success, -1 on failure.
  247. */
  248. static int
  249. my_ber_scanf_value(BerElement *ber, Slapi_Value **value, PRBool *deleted)
  250. {
  251. struct berval *attrval = NULL;
  252. unsigned long len;
  253. unsigned long tag;
  254. CSN *csn = NULL;
  255. char csnstring[CSN_STRSIZE + 1];
  256. CSNType csntype;
  257. char *lasti;
  258. PR_ASSERT(ber && value && deleted);
  259. *value = NULL;
  260. if (NULL == ber && NULL == value)
  261. {
  262. slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name, "my_ber_scanf_value BAD 1\n");
  263. goto loser;
  264. }
  265. /* Each value is a sequence */
  266. if (ber_scanf(ber, "{O", &attrval) == -1)
  267. {
  268. slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name, "my_ber_scanf_value BAD 2\n");
  269. goto loser;
  270. }
  271. /* Allocate and fill in the attribute value */
  272. if ((*value = slapi_value_new_berval(attrval)) == NULL)
  273. {
  274. slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name, "my_ber_scanf_value BAD 3\n");
  275. goto loser;
  276. }
  277. /* check if this is a deleted value */
  278. if (ber_peek_tag(ber, &len) == LBER_BOOLEAN)
  279. {
  280. if (ber_scanf(ber, "b", deleted) == -1)
  281. {
  282. slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name, "my_ber_scanf_value BAD 4\n");
  283. goto loser;
  284. }
  285. }
  286. else /* default is present value */
  287. {
  288. *deleted = PR_FALSE;
  289. }
  290. /* Read the sequence of CSNs */
  291. for (tag = ber_first_element(ber, &len, &lasti);
  292. tag != LBER_ERROR && tag != LBER_END_OF_SEQORSET;
  293. tag = ber_next_element(ber, &len, lasti))
  294. {
  295. long csntype_tmp;
  296. /* Each CSN is in a sequence that includes a csntype and CSN */
  297. len = CSN_STRSIZE;
  298. if (ber_scanf(ber, "{es}", &csntype_tmp, csnstring, &len) == -1)
  299. {
  300. slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name, "my_ber_scanf_value BAD 7 - bval is %s\n", attrval->bv_val);
  301. goto loser;
  302. }
  303. switch (csntype_tmp)
  304. {
  305. case CSN_TYPE_VALUE_UPDATED_ON_WIRE:
  306. csntype = CSN_TYPE_VALUE_UPDATED;
  307. break;
  308. case CSN_TYPE_VALUE_DELETED_ON_WIRE:
  309. csntype = CSN_TYPE_VALUE_DELETED;
  310. break;
  311. case CSN_TYPE_VALUE_DISTINGUISHED_ON_WIRE:
  312. csntype = CSN_TYPE_VALUE_DISTINGUISHED;
  313. break;
  314. default:
  315. slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name, "Error: preposterous CSN type "
  316. "%d received during total update.\n", csntype_tmp);
  317. goto loser;
  318. }
  319. csn = csn_new_by_string(csnstring);
  320. if (csn == NULL)
  321. {
  322. slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name, "my_ber_scanf_value BAD 8\n");
  323. goto loser;
  324. }
  325. value_add_csn(*value, csntype, csn);
  326. csn_free (&csn);
  327. }
  328. if (ber_scanf(ber, "}") == -1) /* End of annotated attribute value seq */
  329. {
  330. slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name, "my_ber_scanf_value BAD 10\n");
  331. goto loser;
  332. }
  333. if (attrval)
  334. ber_bvfree(attrval);
  335. return 0;
  336. loser:
  337. /* Free any stuff we allocated */
  338. if (csn)
  339. csn_free (&csn);
  340. if (attrval)
  341. ber_bvfree(attrval);
  342. if (value)
  343. {
  344. slapi_value_free (value);
  345. }
  346. return -1;
  347. }
  348. static int
  349. my_ber_scanf_attr (BerElement *ber, Slapi_Attr **attr, PRBool *deleted)
  350. {
  351. char *attrtype = NULL;
  352. CSN *attr_deletion_csn = NULL;
  353. PRBool val_deleted;
  354. char *lasti;
  355. unsigned long len;
  356. unsigned long tag;
  357. char *str;
  358. int rc;
  359. Slapi_Value *value;
  360. PR_ASSERT (ber && attr && deleted);
  361. /* allocate the attribute */
  362. *attr = slapi_attr_new ();
  363. if (attr == NULL)
  364. {
  365. goto loser;
  366. }
  367. if (ber_scanf(ber, "{a", &attrtype) == -1) /* Begin sequence for this attr */
  368. {
  369. goto loser;
  370. }
  371. slapi_attr_init(*attr, attrtype);
  372. slapi_ch_free ((void **)&attrtype);
  373. /* The attribute deletion CSN is next and is optional? */
  374. if (ber_peek_tag(ber, &len) == LBER_OCTETSTRING)
  375. {
  376. if (ber_scanf(ber, "a", &str) == -1)
  377. {
  378. goto loser;
  379. }
  380. attr_deletion_csn = csn_new_by_string(str);
  381. slapi_ch_free((void **)&str);
  382. }
  383. if (attr_deletion_csn)
  384. {
  385. rc = attr_set_deletion_csn(*attr, attr_deletion_csn);
  386. csn_free (&attr_deletion_csn);
  387. if (rc != 0)
  388. {
  389. goto loser;
  390. }
  391. }
  392. /* The "attribute deleted" flag is next, and is optional */
  393. if (ber_peek_tag(ber, &len) == LBER_BOOLEAN)
  394. {
  395. if (ber_scanf(ber, "b", deleted) == -1)
  396. {
  397. goto loser;
  398. }
  399. }
  400. else /* default is present */
  401. {
  402. *deleted = PR_FALSE;
  403. }
  404. /* loop over the list of attribute values */
  405. for (tag = ber_first_element(ber, &len, &lasti);
  406. tag != LBER_ERROR && tag != LBER_END_OF_SEQORSET;
  407. tag = ber_next_element(ber, &len, lasti))
  408. {
  409. value = NULL;
  410. if (my_ber_scanf_value(ber, &value, &val_deleted) == -1)
  411. {
  412. goto loser;
  413. }
  414. if (val_deleted)
  415. {
  416. /* Add the value to the attribute */
  417. if (attr_add_deleted_value(*attr, value) == -1) /* attr has ownership of value */
  418. {
  419. goto loser;
  420. }
  421. }
  422. else
  423. {
  424. /* Add the value to the attribute */
  425. if (slapi_attr_add_value(*attr, value) == -1) /* attr has ownership of value */
  426. {
  427. goto loser;
  428. }
  429. }
  430. if (value)
  431. slapi_value_free(&value);
  432. }
  433. if (ber_scanf(ber, "}") == -1) /* End sequence for this attribute */
  434. {
  435. goto loser;
  436. }
  437. return 0;
  438. loser:
  439. if (*attr)
  440. slapi_attr_free (attr);
  441. if (value)
  442. slapi_value_free (&value);
  443. return -1;
  444. }
  445. /*
  446. * Extract the payload from a total update extended operation,
  447. * decode it, and produce a Slapi_Entry structure representing a new
  448. * entry to be added to the local database.
  449. */
  450. static int
  451. decode_total_update_extop(Slapi_PBlock *pb, Slapi_Entry **ep)
  452. {
  453. BerElement *tmp_bere = NULL;
  454. Slapi_Entry *e = NULL;
  455. Slapi_Attr *attr = NULL;
  456. char *str = NULL;
  457. CSN *dn_csn = NULL;
  458. struct berval *extop_value = NULL;
  459. char *extop_oid = NULL;
  460. unsigned long len;
  461. char *lasto;
  462. unsigned long tag;
  463. int rc;
  464. PRBool deleted;
  465. PR_ASSERT(NULL != pb);
  466. PR_ASSERT(NULL != ep);
  467. slapi_pblock_get(pb, SLAPI_EXT_OP_REQ_OID, &extop_oid);
  468. slapi_pblock_get(pb, SLAPI_EXT_OP_REQ_VALUE, &extop_value);
  469. if (NULL == extop_oid ||
  470. strcmp(extop_oid, REPL_NSDS50_REPLICATION_ENTRY_REQUEST_OID) != 0 ||
  471. NULL == extop_value)
  472. {
  473. /* Bogus */
  474. goto loser;
  475. }
  476. if ((tmp_bere = ber_init(extop_value)) == NULL)
  477. {
  478. goto loser;
  479. }
  480. if ((e = slapi_entry_alloc()) == NULL)
  481. {
  482. goto loser;
  483. }
  484. if (ber_scanf(tmp_bere, "{") == -1) /* Begin outer sequence */
  485. {
  486. goto loser;
  487. }
  488. /* The entry's uniqueid is first */
  489. if (ber_scanf(tmp_bere, "a", &str) == -1)
  490. {
  491. goto loser;
  492. }
  493. slapi_entry_set_uniqueid(e, str);
  494. str = NULL; /* Slapi_Entry now owns the uniqueid */
  495. /* The entry's DN is next */
  496. if (ber_scanf(tmp_bere, "a", &str) == -1)
  497. {
  498. goto loser;
  499. }
  500. slapi_entry_set_dn(e, str);
  501. str = NULL; /* Slapi_Entry now owns the dn */
  502. /* Get the attributes */
  503. for ( tag = ber_first_element( tmp_bere, &len, &lasto );
  504. tag != LBER_ERROR && tag != LBER_END_OF_SEQORSET;
  505. tag = ber_next_element( tmp_bere, &len, lasto ) )
  506. {
  507. if (my_ber_scanf_attr (tmp_bere, &attr, &deleted) != 0)
  508. {
  509. goto loser;
  510. }
  511. /* Add the attribute to the entry */
  512. if (deleted)
  513. entry_add_deleted_attribute_wsi(e, attr); /* entry now owns attr */
  514. else
  515. entry_add_present_attribute_wsi(e, attr); /* entry now owns attr */
  516. attr = NULL;
  517. }
  518. if (ber_scanf(tmp_bere, "}") == -1) /* End sequence for this entry */
  519. {
  520. goto loser;
  521. }
  522. /* Check for ldapsubentries and tombstone entries to set flags properly */
  523. slapi_entry_attr_find(e, "objectclass", &attr);
  524. if (attr != NULL) {
  525. struct berval bv;
  526. bv.bv_val = "ldapsubentry";
  527. bv.bv_len = strlen(bv.bv_val);
  528. if (slapi_attr_value_find(attr, &bv) == 0) {
  529. slapi_entry_set_flag(e, SLAPI_ENTRY_LDAPSUBENTRY);
  530. }
  531. bv.bv_val = SLAPI_ATTR_VALUE_TOMBSTONE;
  532. bv.bv_len = strlen(bv.bv_val);
  533. if (slapi_attr_value_find(attr, &bv) == 0) {
  534. slapi_entry_set_flag(e, SLAPI_ENTRY_FLAG_TOMBSTONE);
  535. }
  536. }
  537. /* If we get here, the entry is properly constructed. Return it. */
  538. rc = 0;
  539. *ep = e;
  540. goto free_and_return;
  541. loser:
  542. rc = -1;
  543. /* slapi_ch_free accepts NULL pointer */
  544. slapi_ch_free((void **)&str);
  545. if (NULL != dn_csn)
  546. {
  547. csn_free(&dn_csn);
  548. }
  549. if (attr != NULL)
  550. {
  551. slapi_attr_free (&attr);
  552. }
  553. if (NULL != e)
  554. {
  555. slapi_entry_free (e);
  556. }
  557. *ep = NULL;
  558. slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name, "Error: could not decode extended "
  559. "operation containing entry for total update.\n");
  560. free_and_return:
  561. if (NULL != tmp_bere)
  562. {
  563. ber_free(tmp_bere, 1);
  564. tmp_bere = NULL;
  565. }
  566. return rc;
  567. }
  568. /*
  569. * This plugin entry point is called whenever an NSDS50ReplicationEntry
  570. * extended operation is received.
  571. */
  572. int
  573. ___multimaster_extop_NSDS50ReplicationEntry(Slapi_PBlock *pb)
  574. {
  575. int rc;
  576. Slapi_Entry *e = NULL;
  577. Slapi_Connection *conn = NULL;
  578. int connid, opid;
  579. connid = 0;
  580. slapi_pblock_get(pb, SLAPI_CONN_ID, &connid);
  581. opid = 0;
  582. slapi_pblock_get(pb, SLAPI_OPERATION_ID, &opid);
  583. /* Decode the extended operation */
  584. rc = decode_total_update_extop(pb, &e);
  585. if (0 == rc)
  586. {
  587. #ifdef notdef
  588. /*
  589. * Just spew LDIF so we're sure we got it right. Later we'll firehose
  590. * this into the database import code
  591. */
  592. int len;
  593. char *str = slapi_entry2str_with_options(e, &len,SLAPI_DUMP_UNIQUEID);
  594. puts(str);
  595. free(str);
  596. #endif
  597. rc = slapi_import_entry (pb, e);
  598. /* slapi_import_entry return an LDAP error in case of problem
  599. * LDAP_BUSY is used to indicate that the import queue is full
  600. * and that flow control must happen to stop the supplier
  601. * from sending entries
  602. */
  603. if ((rc != LDAP_SUCCESS) && (rc != LDAP_BUSY))
  604. {
  605. const char *dn = slapi_entry_get_dn_const(e);
  606. slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name,
  607. "Error %d: could not import entry dn %s "
  608. "for total update operation conn=%d op=%d\n",
  609. rc, dn, connid, opid);
  610. rc = -1;
  611. }
  612. }
  613. else
  614. {
  615. slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name,
  616. "Error %d: could not decode the total update extop "
  617. "for total update operation conn=%d op=%d\n",
  618. rc, connid, opid);
  619. }
  620. if ((rc != 0) && (rc != LDAP_BUSY))
  621. {
  622. /* just disconnect from the supplier. bulk import is stopped when
  623. connection object is destroyed */
  624. slapi_pblock_get (pb, SLAPI_CONNECTION, &conn);
  625. if (conn)
  626. {
  627. slapi_disconnect_server(conn);
  628. }
  629. /* cleanup */
  630. if (e)
  631. {
  632. slapi_entry_free (e);
  633. }
  634. }
  635. return rc;
  636. }