| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804 |
- /** BEGIN COPYRIGHT BLOCK
- * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
- * Copyright (C) 2005 Red Hat, Inc.
- * All rights reserved.
- *
- * License: GPL (version 3 or any later version).
- * See LICENSE for details.
- * END COPYRIGHT BLOCK **/
- #ifdef HAVE_CONFIG_H
- # include <config.h>
- #endif
- /* cl4_api.h - implementation of the minimal interface to 4.0 changelog necessary to
- link 4.0 changelog to 5.0 replication
- */
- #include "repl.h"
- #include "cl4_api.h"
- #include "csnpl.h"
- #include "cl4.h"
- /*** Data Structures ***/
- /* changelog internal data */
- typedef struct cl4priv
- {
- CSNPL *csnPL; /* csn pending list */
- int regID; /* csn function registration id */
- }CL4Private;
- /* callback data to get result of internal operations */
- typedef struct cl4ret
- {
- int err; /* error code */
- Slapi_Entry *e; /* target entry */
- }CL4Ret;
- /* Global Data */
- static CL4Private s_cl4Desc; /* represents changelog state */
- /*** Helper functions forward declarations ***/
- static int _cl4WriteOperation (const slapi_operation_parameters *op);
- static void _cl4AssignCSNCallback (const CSN *csn, void *data);
- static void _cl4AbortCSNCallback (const CSN *csn, void *data);
- static char* _cl4MakeCSNDN (const CSN* csn);
- static int _cl4GetEntry (const CSN *csn, Slapi_Entry **entry);
- static void _cl4ResultCallback (int err, void *callback_data);
- static int _cl4EntryCallback (Slapi_Entry *e, void *callback_data);
- static PRBool _cl4CanAssignChangeNumber (const CSN *csn);
- static int _cl4ResolveTargetDN (Slapi_Entry *entry, Slapi_DN **newTargetDN);
- static int _cl4GetTargetEntry (Slapi_DN *targetDN, const char *uniqueid, Slapi_Entry **entry);
- static int _cl4FindTargetDN (const CSN *csn, const char *uniqueid,
- const Slapi_DN *targetSDN, Slapi_DN **newTargetDN);
- static int _cl4AssignChangeNumber (changeNumber *cnum);
- static int _cl4UpdateEntry (const CSN *csn, const char *changeType, const Slapi_DN *newTargetDN, changeNumber cnum);
- /*** API ***/
- int cl4Init ()
- {
- s_cl4Desc.csnPL = csnplNew ();
- if (s_cl4Desc.csnPL == NULL)
- {
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cl4Init: failed to create CSN pending list\n");
- return CL4_CSNPL_ERROR;
- }
- s_cl4Desc.regID = csnRegisterNewCSNCb(_cl4AssignCSNCallback, NULL,
- _cl4AbortCSNCallback, NULL);
- return CL4_SUCCESS;
- }
- void cl4Cleanup ()
- {
- if (s_cl4Desc.regID >= 0)
- {
- csnRemoveNewCSNCb(s_cl4Desc.regID);
- s_cl4Desc.regID = -1;
- }
- if (s_cl4Desc.csnPL == NULL)
- csnplFree (&s_cl4Desc.csnPL);
- }
- int cl4WriteOperation (const slapi_operation_parameters *op)
- {
- int rc;
- ReplicaId rd;
- if (op == NULL || !IsValidOperation (op))
- {
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cl4WriteEntry: invalid entry\n");
- return CL4_BAD_DATA;
- }
-
- rc = _cl4WriteOperation (op);
- if (rc != CL4_SUCCESS)
- {
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cl4WriteEntry: failed to write changelog entry\n");
- return rc;
- }
- /* the entry is generated by this server - remove the entry from the pending list */
- rd= csn_get_replicaid(op->csn);
- if (rd == slapi_get_replicaid ())
- {
- rc = csnplRemove (s_cl4Desc.csnPL, op->csn);
- if (rc != 0)
- {
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
- "cl4WriteEntry: failed to remove CSN from the pending list\n");
- rc = CL4_CSNPL_ERROR;
- }
- }
- return rc;
- }
- int cl4ChangeTargetDN (const CSN *csn, const char *newDN)
- {
- Slapi_PBlock *pb;
- char *changeEntryDN;
- Slapi_Mods smods;
- int res;
- if (csn == NULL || newDN == NULL)
- {
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cl4ChangeTargetDN: invalid argument\n");
- return CL4_BAD_DATA;
- }
- /* construct dn of the change entry */
- changeEntryDN = _cl4MakeCSNDN (csn);
- if (changeEntryDN == NULL)
- {
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
- "cl4ChangeTargetDN: failed to construct change entry dn\n");
- return CL4_MEMORY_ERROR;
- }
- pb = slapi_pblock_new ();
- slapi_mods_init(&smods, 1);
- slapi_mods_add(&smods, LDAP_MOD_REPLACE | LDAP_MOD_BVALUES, attr_targetdn,
- strlen (newDN), newDN);
- slapi_modify_internal_set_pb(pb, changeEntryDN, slapi_mods_get_ldapmods_byref(&smods),
- NULL, NULL, repl_get_plugin_identity(PLUGIN_LEGACY_REPLICATION), 0);
- slapi_modify_internal_pb (pb);
- slapi_mods_done(&smods);
- slapi_ch_free ((void**)&changeEntryDN);
-
- slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &res);
- slapi_pblock_destroy(pb);
- if (res != LDAP_SUCCESS)
- {
- char s[CSN_STRSIZE];
- slapi_log_error( SLAPI_LOG_FATAL, repl_plugin_name,
- "cl4ChangeTargetDN: an error occured while modifying change entry with csn %s: %s. "
- "Logging of changes is disabled.\n", csn_as_string(csn,PR_FALSE,s), ldap_err2string(res));
- /* GGOODREPL g_set_repl_backend( NULL ); */
- return CL4_LDAP_ERROR;
- }
- return CL4_SUCCESS;
- }
- void cl4AssignChangeNumbers (time_t when, void *arg)
- {
- int rc = CL4_SUCCESS;
- Slapi_Entry *entry;
- CSN *csn = NULL;
- Slapi_DN *newTargetDN;
- changeNumber cnum;
- char *changetype;
- /* we are looping though the entries ready to be commited updating there target dn
- and assigning change numbers */
- while (_cl4GetEntry (csn, &entry) == CL4_SUCCESS)
- {
- /* ONREPL - I think we need to free previous csn */
- csn = csn_new_by_string(slapi_entry_attr_get_charptr (entry, attr_csn));
- /* all conflicts involving this entry have been resolved */
- if (_cl4CanAssignChangeNumber (csn))
- {
- /* figure out the name of the target entry that corresponds to change csn */
- rc = _cl4ResolveTargetDN (entry, &newTargetDN);
- slapi_entry_free (entry);
- if (rc != CL4_SUCCESS)
- {
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "cl4AssignChangeNumbers: failed to resolve target dn\n");
- break;
- }
- _cl4AssignChangeNumber (&cnum);
- changetype = slapi_entry_attr_get_charptr (entry, attr_changetype);
- /* update change entry: write change number and remove csn attribute.
- Note that we leave uniqueid in the entry to avoid an extra update.
- This is ok since uniqueid is an operational attribute not returned
- to the client by default. */
- rc = _cl4UpdateEntry (csn, changetype, newTargetDN, cnum);
- if (newTargetDN)
- {
- slapi_sdn_free (&newTargetDN);
- }
- slapi_ch_free ((void**)&changetype);
- if (rc != CL4_SUCCESS)
- {
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
- "cl4AssignChangeNumbers: failed to update changelog entry\n");
- break;
- }
- }
- else /* went too far */
- {
- slapi_entry_free (entry);
- break;
- }
- }
- }
- /*** Helper Functions ***/
- /* adds new change record to 4.0 changelog */
- static int _cl4WriteOperation (const slapi_operation_parameters *op)
- {
- int rc = CL4_SUCCESS, res;
- char *changeEntryDN, *timeStr;
- Slapi_Entry *e = NULL;
- Slapi_PBlock *pb = NULL;
- Slapi_Value *values[3];
- char s[CSN_STRSIZE];
-
- slapi_log_error (SLAPI_LOG_PLUGIN, repl_plugin_name,
- "_cl4WriteEntry: writing change record with csn %s for dn: \"%s\"\n",
- csn_as_string(op->csn,PR_FALSE,s), op->target_address.dn);
- /* create change entry dn */
- changeEntryDN = _cl4MakeCSNDN (op->csn);
- if (changeEntryDN == NULL)
- {
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
- "_cl4WriteEntry: failed to create entry dn\n");
- return CL4_MEMORY_ERROR;
- }
- /*
- * Create the entry struct, and fill in fields common to all types
- * of change records.
- */
- e = slapi_entry_alloc();
- if (e == NULL)
- {
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
- "_cl4WriteEntry: failed to allocate change entry\n");
- return CL4_MEMORY_ERROR;
- }
- slapi_entry_set_dn(e, slapi_ch_strdup (changeEntryDN));
- /* Set the objectclass attribute */
- values [0] = slapi_value_new (NULL);
- values [1] = slapi_value_new (NULL);
- values [2] = NULL;
- slapi_value_set_string(values[0], "top");
- slapi_value_set_string(values[1], "changelogentry");
- slapi_entry_add_values_sv (e, "objectclass", values);
- /* ONREPL - for now we have to free Slapi_Values since api makes copy;
- this will change when a new set of api is added */
- slapi_value_free (&(values[0]));
- slapi_value_free (&(values[1]));
- /* Set the changeNumber attribute */
- /* Need to set this because it is required by schema */
- slapi_entry_attr_set_charptr (e, attr_changenumber, "0");
- /* Set the targetentrydn attribute */
- if (op->operation_type == SLAPI_OPERATION_ADD) /* use raw dn */
- slapi_entry_attr_set_charptr (e, attr_targetdn, slapi_entry_get_dn (op->p.p_add.target_entry));
- else /* use normolized dn */
- slapi_entry_attr_set_charptr (e, attr_targetdn, op->target_address.dn);
- /* ONREPL - set dbid attribute */
- /* Set the changeTime attribute */
- timeStr = format_localTime (current_time());
- slapi_entry_attr_set_charptr (e, attr_changetime, timeStr);
- slapi_ch_free((void**)&timeStr);
- /*
- * Finish constructing the entry. How to do it depends on the type
- * of modification being logged.
- */
- switch (op->operation_type)
- {
- case SLAPI_OPERATION_ADD: if (entry2reple(e, op->p.p_add.target_entry) != 0 )
- {
- rc = CL4_INTERNAL_ERROR;
- goto done;
- }
- break;
- case SLAPI_OPERATION_MODIFY: if (mods2reple(e, op->p.p_modify.modify_mods) != 0)
- {
- rc = CL4_INTERNAL_ERROR;
- goto done;
- }
- break;
- case SLAPI_OPERATION_MODDN: if (modrdn2reple(e, op->p.p_modrdn.modrdn_newrdn,
- op->p.p_modrdn.modrdn_deloldrdn, op->p.p_modrdn.modrdn_mods) != 0)
- {
- rc = CL4_INTERNAL_ERROR;
- goto done;
- }
- break;
- case SLAPI_OPERATION_DELETE: /* Set the changetype attribute */
- slapi_entry_attr_set_charptr (e, attr_changetype, "delete");
- break;
- }
- pb = slapi_pblock_new (pb);
- slapi_add_entry_internal_set_pb (pb, e, NULL, repl_get_plugin_identity (PLUGIN_LEGACY_REPLICATION), 0);
- slapi_add_internal_pb (pb);
- e = NULL; /* add consumes entry */
-
- slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &res);
- slapi_pblock_destroy(pb);
-
- if (res != LDAP_SUCCESS)
- {
- char s[CSN_STRSIZE];
- slapi_log_error( SLAPI_LOG_FATAL, repl_plugin_name,
- "_cl4WriteEntry: an error occured while adding change entry with csn %s, dn = %s: %s. "
- "Logging of changes is disabled.\n", csn_as_string(op->csn,PR_FALSE,s), op->target_address.dn,
- ldap_err2string(res));
- /* GGOODREPL g_set_repl_backend( NULL ); */
- rc = CL4_LDAP_ERROR;
- }
-
- done:
- slapi_entry_free(e);
- if (changeEntryDN)
- slapi_ch_free((void **) &changeEntryDN);
- return rc;
- }
- static void _cl4AssignCSNCallback (const CSN *csn, void *data)
- {
- int rc;
- if (csn == NULL)
- {
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "_cl4AssignCSNCallback: null csn\n");
- return;
- }
- rc = csnplInsert (s_cl4Desc.csnPL, csn);
- if (rc == -1)
- {
- char s[CSN_STRSIZE];
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
- "_cl4AssignCSNCallback: failed to insert csn %s to the pending list\n",
- csn_as_string(csn,PR_FALSE,s));
- }
- }
- static void _cl4AbortCSNCallback (const CSN *csn, void *data)
- {
- int rc;
- if (csn == NULL)
- {
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "_cl4AbortCSNCallback: null csn\n");
- return;
- }
- rc = csnplRemove (s_cl4Desc.csnPL, csn);
- if (rc == -1)
- {
- char s[CSN_STRSIZE];
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
- "_cl4AbortCSNCallback: failed to remove csn %s from the pending list\n",
- csn_as_string(csn,PR_FALSE,s));
- }
- }
- /* initial dn format: csn=<csn>,<changelog suffix>. For instance, csn=013744022939465,cn=changelog4 */
- static char* _cl4MakeCSNDN (const CSN* csn)
- {
- char *pat, *edn;
- char *suffix = changelog4_get_suffix ();
- char s[CSN_STRSIZE];
- if (suffix == NULL)
- return NULL;
- /* Construct the dn of this change record */
- edn = slapi_ch_smprintf("%s=%s,%s", attr_csn, csn_as_string(csn,PR_FALSE,s), suffix);
- slapi_ch_free ((void **)&suffix);
- return edn;
- }
- static int _cl4GetEntry (const CSN *csn, Slapi_Entry **entry)
- {
- int rc;
- char *suffix = changelog4_get_suffix ();
- int type;
- const char *value;
- CL4Ret ret;
- char s[CSN_STRSIZE];
- if (csn == NULL) /* entry with smallest csn */
- {
- type = SLAPI_SEQ_FIRST;
- value = NULL;
- }
- else /* entry with next csn */
- {
- type = SLAPI_SEQ_NEXT;
- value = csn_as_string(csn,PR_FALSE,s);
- }
- rc = slapi_seq_callback(suffix, type, attr_csn, (char*)value, NULL, 0, &ret, NULL,
- _cl4ResultCallback, _cl4EntryCallback, NULL);
- slapi_ch_free ((void**)&suffix);
- if (rc != 0 || ret.err != 0)
- {
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "_cl4GetEntry: failed to get next changelog entry\n");
- return CL4_INTERNAL_ERROR;
- }
- *entry = ret.e;
- return CL4_SUCCESS;
- }
- static void _cl4ResultCallback (int err, void *callback_data)
- {
- CL4Ret *ret = (CL4Ret *)callback_data;
- if (ret)
- {
- ret->err = err;
- }
- }
- static int _cl4EntryCallback (Slapi_Entry *e, void *callback_data)
- {
- CL4Ret *ret = (CL4Ret *)callback_data;
- if (ret)
- {
- ret->e = slapi_entry_dup (e);
- }
- return 0;
- }
- static PRBool _cl4CanAssignChangeNumber (const CSN *csn)
- {
- CSN *commitCSN = NULL;
- /* th CSN is withtin region that can be commited */
- if (csn && csn_compare(csn, commitCSN) < 0)
- return PR_TRUE;
- return PR_FALSE;
- }
- /* ONREPL - describe algorithm */
- static int _cl4ResolveTargetDN (Slapi_Entry *entry, Slapi_DN **newTargetDN)
- {
- int rc;
- char *csnStr = slapi_entry_attr_get_charptr (entry, attr_csn);
- char *targetdn = slapi_entry_attr_get_charptr (entry, attr_targetdn);
- const char *uniqueid = slapi_entry_get_uniqueid (entry);
- char *changetype = slapi_entry_attr_get_charptr (entry, attr_changetype);
- CSN *csn = csn_new_by_string (csnStr);
- Slapi_Entry *targetEntry = NULL;
- const Slapi_DN *teSDN;
- Slapi_DN *targetSDN;
- const CSN *teDNCSN = NULL;
-
- *newTargetDN = NULL;
- targetSDN = slapi_sdn_new();
- if (strcasecmp (changetype, "add") == 0) /* this is add operation - we have rawdn */
- slapi_sdn_set_dn_byref (targetSDN, targetdn);
- else
- slapi_sdn_set_normdn_byref (targetSDN, targetdn);
- /* read the entry to which the change was applied */
- rc = _cl4GetTargetEntry (targetSDN, uniqueid, &targetEntry);
- if (rc != CL4_SUCCESS)
- {
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "_cl4ResolveTargetDN: failed to get target entry\n");
- goto done;
- }
- teDNCSN = entry_get_dncsn(targetEntry);
- if (teDNCSN == NULL)
- {
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "_cl4ResolveTargetDN: failed to get target entry dn\n");
- rc = CL4_BAD_FORMAT;
- goto done;
- }
-
- if (csn_compare(teDNCSN, csn) <= 0)
- {
- /* the change entry target dn should be the same as target entry dn */
- teSDN = slapi_entry_get_sdn_const(targetEntry);
- /* target dn of change entry is not the same as dn of the target entry - update */
- if (slapi_sdn_compare (teSDN, targetSDN) != 0)
- {
- *newTargetDN = slapi_sdn_dup (targetSDN);
- }
- }
- else /* the target entry was renamed since this change occur - find the right target dn */
- {
- rc = _cl4FindTargetDN (csn, uniqueid, targetSDN, newTargetDN);
- }
- done:;
- if (csnStr)
- slapi_ch_free ((void**)&csnStr);
-
- if (targetdn)
- slapi_ch_free ((void**)&targetdn);
- if (uniqueid)
- slapi_ch_free ((void**)&uniqueid);
- if (changetype)
- slapi_ch_free ((void**)&changetype);
-
- if (targetEntry)
- slapi_entry_free (targetEntry);
- if (targetSDN)
- slapi_sdn_free (&targetSDN);
- return rc;
- }
- static int _cl4GetTargetEntry (Slapi_DN *sdn, const char *uniqueid, Slapi_Entry **entry)
- {
- Slapi_PBlock *pb;
- char filter [128];
- int res, rc = CL4_SUCCESS;
- Slapi_Entry **entries = NULL;
- /* read corresponding database entry based on its uniqueid */
- PR_snprintf (filter, sizeof(filter), "uniqueid=%s", uniqueid);
- pb = slapi_pblock_new ();
- slapi_search_internal_set_pb (pb, (char*)slapi_sdn_get_ndn(sdn), LDAP_SCOPE_SUBTREE, filter, NULL, 0, NULL, NULL,
- repl_get_plugin_identity (PLUGIN_LEGACY_REPLICATION), 0);
- slapi_search_internal_pb (pb);
- if (pb == NULL)
- {
- rc = CL4_LDAP_ERROR;
- goto done;
- }
- slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &res);
- if (res == LDAP_NO_SUCH_OBJECT) /* entry not found */
- {
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "_cl4GetTargetEntry: entry (%s) not found\n",
- slapi_sdn_get_ndn(sdn));
- rc = CL4_NOT_FOUND;
- goto done;
- }
- if (res != LDAP_SUCCESS)
- {
- slapi_log_error( SLAPI_LOG_FATAL, repl_plugin_name,
- "_cl4ResolveTargetDN: an error occured while searching for directory entry with uniqueid %s: %s. "
- "Logging of changes is disabled.\n", uniqueid, ldap_err2string(res));
- /* GGOODREPL g_set_repl_backend( NULL ); */
- rc = CL4_LDAP_ERROR;
- goto done;
- }
-
- slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries);
- if (entries == NULL || entries [0] == NULL)
- {
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "_cl4GetTargetEntry: entry (%s) not found\n",
- slapi_sdn_get_ndn(sdn));
- rc = CL4_NOT_FOUND;
- goto done;
- }
- *entry = slapi_entry_dup (entries[0]);
- done:
- if (pb)
- {
- slapi_free_search_results_internal(pb);
- slapi_pblock_destroy (pb);
- }
-
- return rc;
- }
- static int _cl4FindTargetDN (const CSN *csn, const char *uniqueid,
- const Slapi_DN *targetSDN, Slapi_DN **newTargetDN)
- {
- int rc = CL4_SUCCESS;
- int res, i;
- Slapi_PBlock *pb;
- char *suffix = changelog4_get_suffix ();
- char filter [128];
- Slapi_Entry **entries;
- int minIndex = 0;
- CSN *minCSN = NULL, *curCSN;
- char *curType;
- const Slapi_DN *sdn;
- char s[CSN_STRSIZE];
- *newTargetDN = NULL;
- /* Look for all modifications to the target entry with csn larger than
- this csn. We are only interested in rename operations, but change type
- is currently not indexed */
- PR_snprintf (filter, 128, "&(uniqueid=%s)(csn>%s)", uniqueid, csn_as_string(csn,PR_FALSE,s));
- pb = slapi_pblock_new ();
- slapi_search_internal_set_pb (pb, suffix, LDAP_SCOPE_SUBTREE, filter, NULL, 0, NULL, NULL,
- repl_get_plugin_identity (PLUGIN_LEGACY_REPLICATION), 0);
- slapi_search_internal_pb (pb);
- slapi_ch_free ((void**)&suffix);
- if (pb == NULL)
- {
- rc = CL4_LDAP_ERROR;
- goto done;
- }
- slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &res);
- if (res == LDAP_NO_SUCH_OBJECT) /* entry not found */
- {
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "_cl4FindTargetDN: no entries much filter (%s)\n",
- filter);
- rc = CL4_NOT_FOUND;
- goto done;
- }
- if (res != LDAP_SUCCESS)
- {
- slapi_log_error( SLAPI_LOG_FATAL, repl_plugin_name,
- "_cl4ResolveTargetDN: an error occured while searching change entries matching filter %s: %s. "
- "Logging of changes is disabled.\n", filter, ldap_err2string(res));
- /* GGOODREPL g_set_repl_backend( NULL ); */
- rc = CL4_LDAP_ERROR;
- goto done;
- }
- slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries);
- if (entries == NULL)
- {
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "_cl4FindTargetDN: no entries much filter (%s)\n",
- filter);
- rc = CL4_NOT_FOUND;
- goto done;
- }
- i = 0;
- /* find rename operation with smallest csn - its target dn should be the name
- of our change entry */
- while (entries[i])
- {
- curType = slapi_entry_attr_get_charptr (entries[i], attr_changetype);
- if (curType && strcasecmp (curType, "modrdn") == 0)
- {
- curCSN = csn_new_by_string (slapi_entry_attr_get_charptr (entries[i], attr_csn));
- if (minCSN == NULL || csn_compare (curCSN, minCSN) < 0)
- {
- minCSN = curCSN;
- minIndex = i;
- }
- }
- if (curType)
- slapi_ch_free ((void**)&curType);
-
- i ++;
- }
- if (curCSN == NULL)
- {
- rc = CL4_NOT_FOUND;
- goto done;
- }
- /* update targetDN of our entry if necessary */
- sdn = slapi_entry_get_sdn_const(entries[minIndex]);
- /* target dn does not match to renaming operation - rename change entry */
- if (slapi_sdn_compare (sdn, targetSDN) != 0)
- *newTargetDN = slapi_sdn_dup (sdn);
- done:
- if (pb)
- {
- slapi_free_search_results_internal(pb);
- slapi_pblock_destroy (pb);
- }
-
- return rc;
- }
- static int _cl4AssignChangeNumber (changeNumber *cnum)
- {
- *cnum = ldapi_assign_changenumber();
- return CL4_SUCCESS;
- }
- static int _cl4UpdateEntry (const CSN *csn, const char *changeType,
- const Slapi_DN *newDN, changeNumber cnum)
- {
- Slapi_PBlock *pb;
- char *dn;
- const char *dnTemp;
- int res;
- Slapi_Mods smods;
- char cnumbuf[32];
- if (csn == NULL || changeType == NULL)
- {
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "_cl4UpdateEntry: invalid argument\n");
- return CL4_BAD_DATA;
- }
- dn = _cl4MakeCSNDN (csn);
- if (dn == NULL)
- {
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "_cl4UpdateEntry: failed to create entry dn\n");
- return CL4_MEMORY_ERROR;
- }
- slapi_mods_init(&smods, 2);
- if (newDN)
- {
- if (strcasecmp (changeType, "add") == 0)
- dnTemp = slapi_sdn_get_dn (newDN);
- else
- dnTemp = slapi_sdn_get_ndn (newDN);
-
- slapi_mods_add(&smods, LDAP_MOD_REPLACE | LDAP_MOD_BVALUES, attr_targetdn,
- strlen (dnTemp), dnTemp);
- }
- /* Set the changeNumber attribute */
- sprintf(cnumbuf, "%lu", cnum);
- slapi_mods_add (&smods, LDAP_MOD_REPLACE | LDAP_MOD_BVALUES, attr_changenumber,
- strlen (cnumbuf), cnumbuf);
- pb = slapi_pblock_new ();
- slapi_modify_internal_set_pb (pb, dn, slapi_mods_get_ldapmods_byref(&smods), NULL, NULL,
- repl_get_plugin_identity (PLUGIN_LEGACY_REPLICATION), 0);
- slapi_modify_internal_pb (pb);
- slapi_mods_done(&smods);
- slapi_ch_free ((void**)&dn);
- if (pb == NULL)
- {
- return CL4_LDAP_ERROR;
- }
-
- slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &res);
- slapi_pblock_destroy(pb);
- if (res != LDAP_SUCCESS)
- {
- char s[CSN_STRSIZE];
- slapi_log_error( SLAPI_LOG_FATAL, repl_plugin_name,
- "cl4ChangeTargetDN: an error occured while modifying change entry with csn %s: %s. "
- "Logging of changes is disabled.\n", csn_as_string(csn,PR_FALSE,s), ldap_err2string(res));
- /* GGOODREPL g_set_repl_backend( NULL ); */
- return CL4_LDAP_ERROR;
- }
- if ( ldapi_get_first_changenumber() == (changeNumber) 0L )
- {
- ldapi_set_first_changenumber( cnum );
- }
- ldapi_commit_changenumber(cnum);
- return CL4_SUCCESS;
- }
|