retrocl_po.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699
  1. /** BEGIN COPYRIGHT BLOCK
  2. * This Program is free software; you can redistribute it and/or modify it under
  3. * the terms of the GNU General Public License as published by the Free Software
  4. * Foundation; version 2 of the License.
  5. *
  6. * This Program is distributed in the hope that it will be useful, but WITHOUT
  7. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  8. * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  9. *
  10. * You should have received a copy of the GNU General Public License along with
  11. * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
  12. * Place, Suite 330, Boston, MA 02111-1307 USA.
  13. *
  14. * In addition, as a special exception, Red Hat, Inc. gives You the additional
  15. * right to link the code of this Program with code not covered under the GNU
  16. * General Public License ("Non-GPL Code") and to distribute linked combinations
  17. * including the two, subject to the limitations in this paragraph. Non-GPL Code
  18. * permitted under this exception must only link to the code of this Program
  19. * through those well defined interfaces identified in the file named EXCEPTION
  20. * found in the source code files (the "Approved Interfaces"). The files of
  21. * Non-GPL Code may instantiate templates or use macros or inline functions from
  22. * the Approved Interfaces without causing the resulting work to be covered by
  23. * the GNU General Public License. Only Red Hat, Inc. may make changes or
  24. * additions to the list of Approved Interfaces. You must obey the GNU General
  25. * Public License in all respects for all of the Program code and other code used
  26. * in conjunction with the Program except the Non-GPL Code covered by this
  27. * exception. If you modify this file, you may extend this exception to your
  28. * version of the file, but you are not obligated to do so. If you do not wish to
  29. * provide this exception without modification, you must delete this exception
  30. * statement from your version and license this file solely under the GPL without
  31. * exception.
  32. *
  33. *
  34. * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
  35. * Copyright (C) 2005 Red Hat, Inc.
  36. * All rights reserved.
  37. * END COPYRIGHT BLOCK **/
  38. #ifdef HAVE_CONFIG_H
  39. # include <config.h>
  40. #endif
  41. #include "retrocl.h"
  42. static int
  43. entry2reple( Slapi_Entry *e, Slapi_Entry *oe, int optype );
  44. static int
  45. mods2reple( Slapi_Entry *e, LDAPMod **ldm );
  46. static int
  47. modrdn2reple( Slapi_Entry *e, const char *newrdn, int deloldrdn,
  48. LDAPMod **ldm, const char *newsup );
  49. /******************************/
  50. const char *attr_changenumber = "changenumber";
  51. const char *attr_targetdn = "targetdn";
  52. const char *attr_changetype = "changetype";
  53. const char *attr_newrdn = "newrdn";
  54. const char *attr_deleteoldrdn = "deleteoldrdn";
  55. const char *attr_changes = "changes";
  56. const char *attr_newsuperior = "newsuperior";
  57. const char *attr_changetime = "changetime";
  58. const char *attr_objectclass = "objectclass";
  59. const char *attr_nsuniqueid = "nsuniqueid";
  60. const char *attr_isreplicated = "isreplicated";
  61. /*
  62. * Function: make_changes_string
  63. *
  64. * Returns:
  65. *
  66. * Arguments:
  67. *
  68. * Description:
  69. * loop through the LDAPMod struct and construct the changes attribute/
  70. *
  71. */
  72. static lenstr *make_changes_string(LDAPMod **ldm, const char **includeattrs)
  73. {
  74. lenstr *l;
  75. int i, j, len;
  76. int skip;
  77. l = lenstr_new();
  78. for ( i = 0; ldm[ i ] != NULL; i++ ) {
  79. /* If a list of explicit attributes was given, only add those */
  80. if ( NULL != includeattrs ) {
  81. skip = 1;
  82. for ( j = 0; includeattrs[ j ] != NULL; j++ ) {
  83. if ( strcasecmp( includeattrs[ j ], ldm[ i ]->mod_type ) == 0 ) {
  84. skip = 0;
  85. break;
  86. }
  87. }
  88. if ( skip ) {
  89. continue;
  90. }
  91. }
  92. if (SLAPD_UNHASHED_PW_NOLOG == slapi_config_get_unhashed_pw_switch()) {
  93. if (0 == strcasecmp(ldm[ i ]->mod_type, PSEUDO_ATTR_UNHASHEDUSERPASSWORD)) {
  94. /* If nsslapd-unhashed-pw-switch == nolog, skip writing it to cl. */
  95. continue;
  96. }
  97. }
  98. switch ( ldm[ i ]->mod_op & ~LDAP_MOD_BVALUES ) {
  99. case LDAP_MOD_ADD:
  100. addlenstr( l, "add: " );
  101. addlenstr( l, ldm[ i ]->mod_type );
  102. addlenstr( l, "\n" );
  103. break;
  104. case LDAP_MOD_DELETE:
  105. addlenstr( l, "delete: " );
  106. addlenstr( l, ldm[ i ]->mod_type );
  107. addlenstr( l, "\n" );
  108. break;
  109. case LDAP_MOD_REPLACE:
  110. addlenstr( l, "replace: " );
  111. addlenstr( l, ldm[ i ]->mod_type );
  112. addlenstr( l, "\n" );
  113. break;
  114. }
  115. for ( j = 0; ldm[ i ]->mod_bvalues != NULL &&
  116. ldm[ i ]->mod_bvalues[ j ] != NULL; j++ ) {
  117. char *buf = NULL;
  118. char *bufp = NULL;
  119. len = strlen( ldm[ i ]->mod_type );
  120. len = LDIF_SIZE_NEEDED( len,
  121. ldm[ i ]->mod_bvalues[ j ]->bv_len ) + 1;
  122. buf = slapi_ch_malloc( len );
  123. bufp = buf;
  124. slapi_ldif_put_type_and_value_with_options( &bufp, ldm[ i ]->mod_type,
  125. ldm[ i ]->mod_bvalues[ j ]->bv_val,
  126. ldm[ i ]->mod_bvalues[ j ]->bv_len, 0 );
  127. *bufp = '\0';
  128. addlenstr( l, buf );
  129. slapi_ch_free_string( &buf );
  130. }
  131. addlenstr( l, "-\n" );
  132. }
  133. return l;
  134. }
  135. /*
  136. * Function: write_replog_db
  137. * Arguments: be - backend to which this change is being applied
  138. * optype - type of LDAP operation being logged
  139. * dn - distinguished name of entry being changed
  140. * log_m - pointer to the actual change operation on a modify
  141. * flag - only used by modrdn operations - value of deleteoldrdn
  142. * curtime - the current time
  143. * Returns: error code
  144. * Description: Given a change, construct an entry which is to be added to the
  145. * changelog database.
  146. */
  147. static int
  148. write_replog_db(
  149. Slapi_PBlock *pb,
  150. int optype,
  151. char *dn,
  152. LDAPMod **log_m,
  153. int flag,
  154. time_t curtime,
  155. Slapi_Entry *log_e,
  156. const char *newrdn,
  157. LDAPMod **modrdn_mods,
  158. const char *newsuperior
  159. )
  160. {
  161. Slapi_PBlock *newPb = NULL;
  162. changeNumber changenum;
  163. struct berval *vals[ 2 ];
  164. struct berval val;
  165. Slapi_Entry *e;
  166. char chnobuf[ 20 ];
  167. char *edn;
  168. int extensibleObject = 0;
  169. int err = 0;
  170. int ret = LDAP_SUCCESS;
  171. int i;
  172. if (!dn) {
  173. slapi_log_error( SLAPI_LOG_PLUGIN, RETROCL_PLUGIN_NAME, "write_replog_db: NULL dn\n");
  174. return ret;
  175. }
  176. PR_Lock(retrocl_internal_lock);
  177. changenum = retrocl_assign_changenumber();
  178. PR_ASSERT( changenum > 0UL );
  179. slapi_log_error( SLAPI_LOG_PLUGIN, RETROCL_PLUGIN_NAME,
  180. "write_replog_db: write change record %lu for dn: \"%s\"\n",
  181. changenum, dn );
  182. /* Construct the dn of this change record */
  183. edn = slapi_ch_smprintf( "%s=%lu,%s", attr_changenumber, changenum, RETROCL_CHANGELOG_DN);
  184. /*
  185. * Create the entry struct, and fill in fields common to all types
  186. * of change records.
  187. */
  188. vals[ 0 ] = &val;
  189. vals[ 1 ] = NULL;
  190. e = slapi_entry_alloc();
  191. slapi_entry_set_dn( e, slapi_ch_strdup( edn ));
  192. /* Set the objectclass attribute */
  193. val.bv_val = "top";
  194. val.bv_len = 3;
  195. slapi_entry_add_values( e, "objectclass", vals );
  196. val.bv_val = "changelogentry";
  197. val.bv_len = 14;
  198. slapi_entry_add_values( e, "objectclass", vals );
  199. for ( i=0; i<retrocl_nattributes; i++ ) {
  200. char* attributeName = retrocl_attributes[i];
  201. char* attributeAlias = retrocl_aliases[i];
  202. if ( attributeAlias == NULL ) {
  203. attributeAlias = attributeName;
  204. }
  205. if ( strcasecmp( attributeName, attr_nsuniqueid ) == 0 ) {
  206. Slapi_Entry *entry = NULL;
  207. const char *uniqueId = NULL;
  208. slapi_pblock_get( pb, SLAPI_ENTRY_POST_OP, &entry );
  209. if ( entry == NULL ) {
  210. slapi_pblock_get( pb, SLAPI_ENTRY_PRE_OP, &entry );
  211. }
  212. if ( entry == NULL ) continue;
  213. uniqueId = slapi_entry_get_uniqueid( entry );
  214. slapi_log_error( SLAPI_LOG_PLUGIN, RETROCL_PLUGIN_NAME,
  215. "write_replog_db: add %s: \"%s\"\n", attributeAlias, uniqueId );
  216. val.bv_val = (char *)uniqueId;
  217. val.bv_len = strlen( uniqueId );
  218. slapi_entry_add_values( e, attributeAlias, vals );
  219. extensibleObject = 1;
  220. } else if ( strcasecmp( attributeName, attr_isreplicated ) == 0 ) {
  221. int isReplicated = 0;
  222. char *attributeValue = NULL;
  223. slapi_pblock_get( pb, SLAPI_IS_REPLICATED_OPERATION, &isReplicated );
  224. attributeValue = isReplicated ? "TRUE" : "FALSE";
  225. slapi_log_error( SLAPI_LOG_PLUGIN, RETROCL_PLUGIN_NAME,
  226. "write_replog_db: add %s: \"%s\"\n", attributeAlias, attributeValue );
  227. val.bv_val = attributeValue;
  228. val.bv_len = strlen( attributeValue );
  229. slapi_entry_add_values( e, attributeAlias, vals );
  230. extensibleObject = 1;
  231. } else {
  232. Slapi_Entry *entry = NULL;
  233. Slapi_ValueSet *valueSet = NULL;
  234. int type_name_disposition = 0;
  235. char *actual_type_name = NULL;
  236. int flags = 0;
  237. int buffer_flags = 0;
  238. slapi_pblock_get( pb, SLAPI_ENTRY_POST_OP, &entry );
  239. if ( entry != NULL ) {
  240. slapi_vattr_values_get( entry, attributeName, &valueSet,
  241. &type_name_disposition, &actual_type_name, flags, &buffer_flags );
  242. }
  243. if ( valueSet == NULL ) {
  244. slapi_pblock_get( pb, SLAPI_ENTRY_PRE_OP, &entry );
  245. if ( entry != NULL ) {
  246. slapi_vattr_values_get( entry, attributeName, &valueSet,
  247. &type_name_disposition, &actual_type_name, flags, &buffer_flags );
  248. }
  249. }
  250. if ( valueSet == NULL ) continue;
  251. slapi_log_error( SLAPI_LOG_PLUGIN, RETROCL_PLUGIN_NAME,
  252. "write_replog_db: add %s\n", attributeAlias );
  253. slapi_entry_add_valueset( e, attributeAlias, valueSet );
  254. slapi_vattr_values_free( &valueSet, &actual_type_name, buffer_flags );
  255. extensibleObject = 1;
  256. }
  257. }
  258. if ( extensibleObject ) {
  259. val.bv_val = "extensibleObject";
  260. val.bv_len = 16;
  261. slapi_entry_add_values( e, "objectclass", vals );
  262. }
  263. /* Set the changeNumber attribute */
  264. sprintf( chnobuf, "%lu", changenum );
  265. val.bv_val = chnobuf;
  266. val.bv_len = strlen( chnobuf );
  267. slapi_entry_add_values( e, attr_changenumber, vals );
  268. /* Set the targetentrydn attribute */
  269. val.bv_val = dn;
  270. val.bv_len = strlen( dn );
  271. slapi_entry_add_values( e, attr_targetdn, vals );
  272. /* Set the changeTime attribute */
  273. val.bv_val = format_genTime (curtime);
  274. val.bv_len = strlen( val.bv_val );
  275. slapi_entry_add_values( e, attr_changetime, vals );
  276. slapi_ch_free( (void **)&val.bv_val );
  277. /*
  278. * Finish constructing the entry. How to do it depends on the type
  279. * of modification being logged.
  280. */
  281. switch ( optype ) {
  282. case OP_ADD:
  283. if ( entry2reple( e, log_e, OP_ADD ) != 0 ) {
  284. err = SLAPI_PLUGIN_FAILURE;
  285. }
  286. break;
  287. case OP_MODIFY:
  288. if ( mods2reple( e, log_m ) != 0 ) {
  289. err = SLAPI_PLUGIN_FAILURE;
  290. }
  291. break;
  292. case OP_MODRDN:
  293. if ( modrdn2reple( e, newrdn, flag, modrdn_mods, newsuperior ) != 0 ) {
  294. err = SLAPI_PLUGIN_FAILURE;
  295. }
  296. break;
  297. case OP_DELETE:
  298. if (log_e) {
  299. /* we have to log the full entry */
  300. if ( entry2reple( e, log_e, OP_DELETE ) != 0 ) {
  301. err = SLAPI_PLUGIN_FAILURE;
  302. }
  303. } else {
  304. /* Set the changetype attribute */
  305. val.bv_val = "delete";
  306. val.bv_len = 6;
  307. slapi_entry_add_values( e, attr_changetype, vals );
  308. }
  309. break;
  310. default:
  311. slapi_log_error( SLAPI_LOG_FATAL, RETROCL_PLUGIN_NAME,
  312. "replog: Unknown LDAP operation type %d.\n", optype );
  313. err = SLAPI_PLUGIN_FAILURE;
  314. }
  315. /* Call the repl backend to add this entry */
  316. if ( 0 == err ) {
  317. newPb = slapi_pblock_new ();
  318. slapi_add_entry_internal_set_pb( newPb, e, NULL /* controls */,
  319. g_plg_identity[PLUGIN_RETROCL],
  320. /* dont leave entry in cache if main oparation is aborted */
  321. SLAPI_OP_FLAG_NEVER_CACHE);
  322. slapi_add_internal_pb (newPb);
  323. slapi_pblock_get( newPb, SLAPI_PLUGIN_INTOP_RESULT, &ret );
  324. slapi_pblock_destroy(newPb);
  325. if ( 0 != ret ) {
  326. slapi_log_error( SLAPI_LOG_FATAL, RETROCL_PLUGIN_NAME,
  327. "replog: an error occured while adding change "
  328. "number %lu, dn = %s: %s. \n",
  329. changenum, edn, ldap_err2string( ret ));
  330. retrocl_release_changenumber();
  331. } else {
  332. /* Tell the change numbering system this one's committed to disk */
  333. retrocl_commit_changenumber();
  334. }
  335. } else {
  336. slapi_log_error( SLAPI_LOG_FATAL, RETROCL_PLUGIN_NAME,
  337. "An error occurred while constructing "
  338. "change record number %ld.\n", changenum );
  339. retrocl_release_changenumber();
  340. ret = err;
  341. }
  342. PR_Unlock(retrocl_internal_lock);
  343. if ( NULL != edn ) {
  344. slapi_ch_free((void **) &edn);
  345. }
  346. return ret;
  347. }
  348. /*
  349. * Function: entry2reple
  350. * Arguments: e - a partially-constructed Slapi_Entry structure
  351. * oe - the original entry (an entry being added by a client).
  352. * Returns: 0 on success.
  353. * Description: Given an Slapi_Entry struct, construct a changelog entry which will be
  354. * added to the replication database. It is assumed that e points
  355. * to an entry obtained from slapi_entry_alloc().
  356. */
  357. static int
  358. entry2reple( Slapi_Entry *e, Slapi_Entry *oe, int optype )
  359. {
  360. char *p, *estr;
  361. struct berval *vals[ 2 ];
  362. struct berval val;
  363. int len;
  364. vals[ 0 ] = &val;
  365. vals[ 1 ] = NULL;
  366. /* Set the changetype attribute */
  367. if ( optype == OP_ADD ) {
  368. val.bv_val = "add";
  369. val.bv_len = 3;
  370. } else if ( optype == OP_DELETE) {
  371. val.bv_val = "delete";
  372. val.bv_len = 6;
  373. } else {
  374. return (1);
  375. }
  376. slapi_entry_add_values( e, attr_changetype, vals );
  377. estr = slapi_entry2str( oe, &len );
  378. p = estr;
  379. /* Skip over the dn: line */
  380. while (( p = strchr( p, '\n' )) != NULL ) {
  381. p++;
  382. if ( !ldap_utf8isspace( p )) {
  383. break;
  384. }
  385. }
  386. val.bv_val = p;
  387. val.bv_len = len - ( p - estr ); /* length + terminating \0 */
  388. slapi_entry_add_values( e, attr_changes, vals );
  389. slapi_ch_free_string( &estr );
  390. return 0;
  391. }
  392. /*
  393. * Function: mods2reple
  394. * Arguments: e - a partially-constructed Slapi_Entry structure
  395. * ldm - an array of pointers to LDAPMod structures describing the
  396. * change applied.
  397. * Returns: 0 on success.
  398. * Description: Given a pointer to an LDAPMod struct and a dn, construct
  399. * a new entry which will be added to the replication database.
  400. * It is assumed that e points to an entry obtained from
  401. * slapi_entry_alloc().
  402. */
  403. static int
  404. mods2reple( Slapi_Entry *e, LDAPMod **ldm )
  405. {
  406. struct berval val;
  407. struct berval *vals[ 2 ];
  408. lenstr *l;
  409. vals[ 0 ] = &val;
  410. vals[ 1 ] = NULL;
  411. /* Set the changetype attribute */
  412. val.bv_val = "modify";
  413. val.bv_len = 6;
  414. slapi_entry_add_values( e, "changetype", vals );
  415. if (NULL != ldm) {
  416. l = make_changes_string( ldm, NULL );
  417. if ( NULL != l ) {
  418. val.bv_val = l->ls_buf;
  419. val.bv_len = l->ls_len + 1; /* string + terminating \0 */
  420. slapi_entry_add_values( e, attr_changes, vals );
  421. lenstr_free( &l );
  422. }
  423. }
  424. return 0;
  425. }
  426. /*
  427. * Function: modrdn2reple
  428. * Arguments: e - a partially-constructed Slapi_Entry structure
  429. * newrdn - the new relative distinguished name for the entry
  430. * deloldrdn - the "deleteoldrdn" flag provided by the client
  431. * ldm - any modifications applied as a side-effect of the modrdn
  432. * Returns: 0 on success
  433. * Description: Given a dn, a new rdn, and a deleteoldrdn flag, construct
  434. * a new entry which will be added to the replication database reflecting a
  435. * completed modrdn operation. The entry has the same form as above.
  436. * It is assumed that e points to an entry obtained from slapi_entry_alloc().
  437. */
  438. static int
  439. modrdn2reple(
  440. Slapi_Entry *e,
  441. const char *newrdn,
  442. int deloldrdn,
  443. LDAPMod **ldm,
  444. const char *newsuperior
  445. )
  446. {
  447. struct berval val;
  448. struct berval *vals[ 2 ];
  449. lenstr *l;
  450. static const char *lastmodattrs[] = {"modifiersname", "modifytimestamp",
  451. "creatorsname", "createtimestamp",
  452. NULL };
  453. vals[ 0 ] = &val;
  454. vals[ 1 ] = NULL;
  455. val.bv_val = "modrdn";
  456. val.bv_len = 6;
  457. slapi_entry_add_values( e, attr_changetype, vals );
  458. if (newrdn) {
  459. val.bv_val = (char *)newrdn; /* cast away const */
  460. val.bv_len = strlen( newrdn );
  461. slapi_entry_add_values( e, attr_newrdn, vals );
  462. }
  463. if ( deloldrdn == 0 ) {
  464. val.bv_val = "FALSE";
  465. val.bv_len = 5;
  466. } else {
  467. val.bv_val = "TRUE";
  468. val.bv_len = 4;
  469. }
  470. slapi_entry_add_values( e, attr_deleteoldrdn, vals );
  471. if (newsuperior) {
  472. val.bv_val = (char *)newsuperior; /* cast away const */
  473. val.bv_len = strlen(newsuperior);
  474. slapi_entry_add_values(e, attr_newsuperior,vals);
  475. }
  476. if (NULL != ldm) {
  477. l = make_changes_string( ldm, lastmodattrs );
  478. if ( NULL != l ) {
  479. if (l->ls_len) {
  480. val.bv_val = l->ls_buf;
  481. val.bv_len = l->ls_len;
  482. slapi_entry_add_values( e, attr_changes, vals );
  483. }
  484. lenstr_free( &l );
  485. }
  486. }
  487. return 0;
  488. }
  489. /*
  490. * Function: retrocl_postob
  491. *
  492. * Returns: 0 on success
  493. *
  494. * Arguments: pblock, optype (add, del, modify etc)
  495. *
  496. * Description: called from retrocl.c op-specific plugins.
  497. *
  498. * Please be aware that operation threads may be scheduled out between their
  499. * being performed inside of the LDBM database and the changelog plugin
  500. * running. For example, suppose MA and MB are two modify operations on the
  501. * same entry. MA may be performed on the LDBM database, and then block
  502. * before the changelog runs. MB then runs against the LDBM database and then
  503. * is written to the changelog. MA starts running. In the changelog, MB will
  504. * appear to have been performed before MA, but in the LDBM database the
  505. * opposite will have occured.
  506. *
  507. *
  508. */
  509. int retrocl_postob (Slapi_PBlock *pb, int optype)
  510. {
  511. char *dn;
  512. LDAPMod **log_m = NULL;
  513. int flag = 0;
  514. Slapi_Entry *te = NULL;
  515. Slapi_Operation *op = NULL;
  516. LDAPMod **modrdn_mods = NULL;
  517. char *newrdn = NULL;
  518. Slapi_DN *newsuperior = NULL;
  519. Slapi_Backend *be = NULL;
  520. time_t curtime;
  521. int rc = SLAPI_PLUGIN_SUCCESS;
  522. /*
  523. * Check to see if the change was made to the replication backend db.
  524. * If so, don't try to log it to the db (otherwise, we'd get in a loop).
  525. */
  526. (void)slapi_pblock_get( pb, SLAPI_BACKEND, &be );
  527. if (be == NULL) {
  528. LDAPDebug0Args(LDAP_DEBUG_ANY, "retrocl_postob: backend is not set\n");
  529. return SLAPI_PLUGIN_FAILURE;
  530. }
  531. if (slapi_be_logchanges(be) == 0) {
  532. LDAPDebug0Args(LDAP_DEBUG_TRACE,"not applying change if not logging\n");
  533. return SLAPI_PLUGIN_SUCCESS;
  534. }
  535. if (retrocl_be_changelog == NULL || be == retrocl_be_changelog) {
  536. LDAPDebug0Args(LDAP_DEBUG_TRACE,"not applying change if no/cl be\n");
  537. return SLAPI_PLUGIN_SUCCESS;
  538. }
  539. slapi_pblock_get(pb, SLAPI_RESULT_CODE, &rc);
  540. if (rc != LDAP_SUCCESS) {
  541. LDAPDebug1Arg(LDAP_DEBUG_TRACE,"not applying change if op failed %d\n",rc);
  542. /* this could also mean that the changenumber is no longer correct
  543. * set a flag to check at next assignment
  544. */
  545. retrocl_set_check_changenumber();
  546. return SLAPI_PLUGIN_SUCCESS;
  547. }
  548. if (slapi_op_abandoned(pb)) {
  549. LDAPDebug0Args(LDAP_DEBUG_PLUGIN,"not applying change if op abandoned\n");
  550. return SLAPI_PLUGIN_SUCCESS;
  551. }
  552. curtime = current_time();
  553. (void)slapi_pblock_get( pb, SLAPI_ORIGINAL_TARGET_DN, &dn );
  554. /* change number could be retrieved from Operation extension stored in
  555. * the pblock, or else it needs to be made dynamically. */
  556. /* get the operation extension and retrieve the change number */
  557. slapi_pblock_get( pb, SLAPI_OPERATION, &op );
  558. if (op == NULL) {
  559. LDAPDebug0Args(LDAP_DEBUG_TRACE,"not applying change if no op\n");
  560. return SLAPI_PLUGIN_SUCCESS;
  561. }
  562. if (operation_is_flag_set(op, OP_FLAG_TOMBSTONE_ENTRY)){
  563. LDAPDebug0Args(LDAP_DEBUG_TRACE,"not applying change for nsTombstone entries\n");
  564. return SLAPI_PLUGIN_SUCCESS;
  565. }
  566. switch ( optype ) {
  567. case OP_MODIFY:
  568. (void)slapi_pblock_get( pb, SLAPI_MODIFY_MODS, &log_m );
  569. break;
  570. case OP_ADD:
  571. /*
  572. * For adds, we want the unnormalized dn, so we can preserve
  573. * spacing, case, when replicating it.
  574. */
  575. (void)slapi_pblock_get( pb, SLAPI_ADD_ENTRY, &te );
  576. if ( NULL != te ) {
  577. dn = slapi_entry_get_dn( te );
  578. }
  579. break;
  580. case OP_DELETE:
  581. if (retrocl_log_deleted)
  582. (void)slapi_pblock_get(pb, SLAPI_ENTRY_PRE_OP, &te);
  583. break;
  584. case OP_MODRDN:
  585. /* newrdn is used just for logging; no need to be normalized */
  586. (void)slapi_pblock_get( pb, SLAPI_MODRDN_NEWRDN, &newrdn );
  587. (void)slapi_pblock_get( pb, SLAPI_MODRDN_DELOLDRDN, &flag );
  588. (void)slapi_pblock_get( pb, SLAPI_MODIFY_MODS, &modrdn_mods );
  589. (void)slapi_pblock_get( pb, SLAPI_MODRDN_NEWSUPERIOR_SDN, &newsuperior );
  590. break;
  591. }
  592. /* check if we should log change to retro changelog, and
  593. * if so, do it here */
  594. if((rc = write_replog_db( pb, optype, dn, log_m, flag, curtime, te,
  595. newrdn, modrdn_mods, slapi_sdn_get_dn(newsuperior) )))
  596. {
  597. slapi_log_error(SLAPI_LOG_FATAL, "retrocl-plugin",
  598. "retrocl_postob: operation failure [%d]\n", rc);
  599. if(rc < 0){
  600. rc = LDAP_OPERATIONS_ERROR;
  601. }
  602. slapi_pblock_set(pb, SLAPI_RESULT_CODE, &rc);
  603. rc = SLAPI_PLUGIN_FAILURE;
  604. }
  605. return rc;
  606. }