1
0

retrocl_po.c 21 KB

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