summaryrefslogtreecommitdiffstats
path: root/ldap/servers/slapd/back-ldbm/import-threads.c
diff options
context:
space:
mode:
Diffstat (limited to 'ldap/servers/slapd/back-ldbm/import-threads.c')
-rw-r--r--ldap/servers/slapd/back-ldbm/import-threads.c213
1 files changed, 174 insertions, 39 deletions
diff --git a/ldap/servers/slapd/back-ldbm/import-threads.c b/ldap/servers/slapd/back-ldbm/import-threads.c
index dcc44517..4525449e 100644
--- a/ldap/servers/slapd/back-ldbm/import-threads.c
+++ b/ldap/servers/slapd/back-ldbm/import-threads.c
@@ -402,7 +402,7 @@ import_producer(void *param)
fd = -1;
detected_eof = finished = 0;
- /* we loop around reading the input files and processing each ntry
+ /* we loop around reading the input files and processing each entry
* as we read it.
*/
while (! finished) {
@@ -1173,11 +1173,11 @@ upgradedn_add_to_list(struct upgradedn_attr **ud_list,
* If both are false, skip the entry and go to next
* If either is true, create an entry which contains a correctly normalized
* DN attribute values in e_attr list and the original entrydn in the
- * deleted attribute list e_deleted_attrs.
+ * deleted attribute list e_aux_attrs.
*
* If FLAG_UPGRADEDNFORMAT is set, worker_threads for indexing DN syntax
- * attributes are brought up. Foreman thread updates entrydn index
- * as well as the entry itself in the id2entry.db#.
+ * attributes (+ cn & ou) are brought up. Foreman thread updates entrydn
+ * or entryrd index as well as the entry itself in the id2entry.db#.
*
* Note: QUIT state for info->state is introduced for DRYRUN mode to
* distinguish the intentional QUIT (found the dn upgrade candidate)
@@ -1314,7 +1314,8 @@ upgradedn_producer(void *param)
rc = get_value_from_string((const char *)data.dptr, "rdn", &rdn);
if (rc) {
/* data.dptr may not include rdn: ..., try "dn: ..." */
- e = slapi_str2entry( data.dptr, 0 );
+ e = slapi_str2entry(data.dptr,
+ SLAPI_STR2ENTRY_USE_OBSOLETE_DNFORMAT);
} else {
char *dn = NULL;
struct backdn *bdn =
@@ -1382,11 +1383,13 @@ upgradedn_producer(void *param)
"entryrdn_lookup_dn returned: %s, "
"and set to dn cache\n", dn);
}
- e = slapi_str2entry_ext( dn, data.dptr, 0 );
+ e = slapi_str2entry_ext(dn, data.dptr,
+ SLAPI_STR2ENTRY_USE_OBSOLETE_DNFORMAT);
slapi_ch_free_string(&rdn);
}
} else {
- e = slapi_str2entry(data.data, 0);
+ e =
+ slapi_str2entry(data.data, SLAPI_STR2ENTRY_USE_OBSOLETE_DNFORMAT);
}
slapi_ch_free(&(data.data));
if ( NULL == e ) {
@@ -1556,7 +1559,7 @@ upgradedn_producer(void *param)
skipit = 0;
for (ud_ptr = ud_list; ud_ptr; ud_ptr = ud_ptr->ud_next) {
- /* Move the current value to e_deleted_attrs. */
+ /* Move the current value to e_aux_attrs. */
/* entryrdn is special since it does not have an attribute in db */
if (0 == strcmp(ud_ptr->ud_type, LDBM_ENTRYRDN_STR)) {
/* entrydn contains half normalized value in id2entry,
@@ -1569,26 +1572,26 @@ upgradedn_producer(void *param)
value = slapi_value_new_string(ud_ptr->ud_value);
slapi_attr_add_value(a, value);
slapi_value_free(&value);
- attrlist_add(&e->e_deleted_attrs, a);
+ attrlist_add(&e->e_aux_attrs, a);
} else { /* except "entryrdn" */
ud_attr = attrlist_find(e->e_attrs, ud_ptr->ud_type);
if (ud_attr) {
/* We have to normalize the orignal string to generate
the key in the index.
*/
- a = attrlist_find(e->e_deleted_attrs, ud_ptr->ud_type);
+ a = attrlist_find(e->e_aux_attrs, ud_ptr->ud_type);
if (!a) {
a = slapi_attr_new();
slapi_attr_init(a, ud_ptr->ud_type);
} else {
- a = attrlist_remove(&e->e_deleted_attrs,
+ a = attrlist_remove(&e->e_aux_attrs,
ud_ptr->ud_type);
}
slapi_dn_normalize_case_original(ud_ptr->ud_value);
value = slapi_value_new_string(ud_ptr->ud_value);
slapi_attr_add_value(a, value);
slapi_value_free(&value);
- attrlist_add(&e->e_deleted_attrs, a);
+ attrlist_add(&e->e_aux_attrs, a);
}
}
}
@@ -1742,19 +1745,52 @@ import_wait_for_space_in_fifo(ImportJob *job, size_t new_esize)
}
/* helper function for the foreman: */
-static int foreman_do_parentid(ImportJob *job, struct backentry *entry,
- struct attrinfo *parentid_ai)
+static int
+foreman_do_parentid(ImportJob *job, FifoItem *fi, struct attrinfo *parentid_ai)
{
backend *be = job->inst->inst_be;
Slapi_Value **svals = NULL;
Slapi_Attr *attr = NULL;
int idl_disposition = 0;
int ret = 0;
+ struct backentry *entry = fi->entry;
+
+ if (job->flags & FLAG_UPGRADEDNFORMAT) {
+ /* Get the parentid attribute value from deleted attr list */
+ Slapi_Value *value = NULL;
+ Slapi_Attr *pid_to_del =
+ attrlist_remove(&entry->ep_entry->e_aux_attrs, "parentid");
+ if (pid_to_del) {
+ /* Delete it. */
+ ret = slapi_attr_first_value(pid_to_del, &value);
+ if (ret < 0) {
+ import_log_notice(job,
+ "Error: retrieving parentid value (error %d)",
+ ret);
+ } else {
+ const struct berval *bval =
+ slapi_value_get_berval((const Slapi_Value *)value);
+ ret = index_addordel_string(be, "parentid",
+ bval->bv_val, entry->ep_id,
+ BE_INDEX_DEL|BE_INDEX_EQUALITY|BE_INDEX_NORMALIZED,
+ NULL);
+ if (ret) {
+ import_log_notice(job,
+ "Error: deleting %s from parentid index "
+ "(error %d: %s)",
+ bval->bv_val, ret, dblayer_strerror(ret));
+ return ret;
+ }
+ }
+ slapi_attr_free(&pid_to_del);
+ }
+ }
if (slapi_entry_attr_find(entry->ep_entry, LDBM_PARENTID_STR, &attr) == 0) {
svals = attr_get_present_values(attr);
- ret = index_addordel_values_ext_sv(be, LDBM_PARENTID_STR, svals, NULL, entry->ep_id,
- BE_INDEX_ADD, NULL, &idl_disposition, NULL);
+ ret = index_addordel_values_ext_sv(be, LDBM_PARENTID_STR, svals, NULL,
+ entry->ep_id, BE_INDEX_ADD,
+ NULL, &idl_disposition, NULL);
if (idl_disposition != IDL_INSERT_NORMAL) {
char *attr_value = slapi_value_get_berval(svals[0])->bv_val;
ID parent_id = atol(attr_value);
@@ -1784,12 +1820,13 @@ foreman_do_entrydn(ImportJob *job, FifoItem *fi)
struct berval bv;
int err = 0, ret = 0;
IDList *IDL;
+ struct backentry *entry = fi->entry;
if (job->flags & FLAG_UPGRADEDNFORMAT) {
/* Get the entrydn attribute value from deleted attr list */
Slapi_Value *value = NULL;
Slapi_Attr *entrydn_to_del =
- attrlist_remove(&fi->entry->ep_entry->e_deleted_attrs, "entrydn");
+ attrlist_remove(&entry->ep_entry->e_aux_attrs, "entrydn");
if (entrydn_to_del) {
/* Delete it. */
@@ -1802,8 +1839,7 @@ foreman_do_entrydn(ImportJob *job, FifoItem *fi)
const struct berval *bval =
slapi_value_get_berval((const Slapi_Value *)value);
ret = index_addordel_string(be, "entrydn",
- bval->bv_val,
- fi->entry->ep_id,
+ bval->bv_val, entry->ep_id,
BE_INDEX_DEL|BE_INDEX_EQUALITY|BE_INDEX_NORMALIZED,
NULL);
if (ret) {
@@ -1819,7 +1855,7 @@ foreman_do_entrydn(ImportJob *job, FifoItem *fi)
}
/* insert into the entrydn index */
- bv.bv_val = (void*)backentry_get_ndn(fi->entry); /* jcm - Had to cast away const */
+ bv.bv_val = (void*)backentry_get_ndn(entry); /* jcm - Had to cast away const */
bv.bv_len = strlen(bv.bv_val);
/* We need to check here whether the DN is already present in
@@ -1833,14 +1869,24 @@ foreman_do_entrydn(ImportJob *job, FifoItem *fi)
if (job->flags & FLAG_UPGRADEDNFORMAT) {
/*
* In the UPGRADEDNFORMAT case, if entrydn value exists,
- * that means entrydn is not upgraded. And it is normal.
- * We could add entrydn only when the value is not found in the db.
+ * that means either 1) entrydn is not upgraded (ID == entry->ep_id)
+ * or 2) a duplicated entry is found (ID != entry->ep_id).
+ * (1) is normal. For (2), need to return a specific error
+ * LDBM_ERROR_FOUND_DUPDN.
+ * Otherwise, add entrydn to the entrydn index file.
*/
if (IDL) {
+ ID id = idl_firstid(IDL); /* entrydn is a single attr */
idl_free(IDL);
+ if (id != entry->ep_id) { /* case (2) */
+ import_log_notice(job, "Duplicated entrydn detected: \"%s\": "
+ "Entry ID: (%d, %d)",
+ bv.bv_val, id, entry->ep_id);
+ return LDBM_ERROR_FOUND_DUPDN;
+ }
} else {
ret = index_addordel_string(be, "entrydn",
- bv.bv_val, fi->entry->ep_id,
+ bv.bv_val, entry->ep_id,
BE_INDEX_ADD|BE_INDEX_NORMALIZED, NULL);
if (ret) {
import_log_notice(job, "Error writing entrydn index "
@@ -1855,7 +1901,7 @@ foreman_do_entrydn(ImportJob *job, FifoItem *fi)
/* IMPOSTER ! Get thee hence... */
import_log_notice(job, "WARNING: Skipping duplicate entry "
"\"%s\" found at line %d of file \"%s\"",
- slapi_entry_get_dn(fi->entry->ep_entry),
+ slapi_entry_get_dn(entry->ep_entry),
fi->line, fi->filename);
idl_free(IDL);
/* skip this one */
@@ -1863,7 +1909,7 @@ foreman_do_entrydn(ImportJob *job, FifoItem *fi)
job->skipped++;
return -1; /* skip to next entry */
}
- ret = index_addordel_string(be, "entrydn", bv.bv_val, fi->entry->ep_id,
+ ret = index_addordel_string(be, "entrydn", bv.bv_val, entry->ep_id,
BE_INDEX_ADD|BE_INDEX_NORMALIZED, NULL);
if (ret) {
import_log_notice(job, "Error writing entrydn index "
@@ -1882,12 +1928,13 @@ foreman_do_entryrdn(ImportJob *job, FifoItem *fi)
{
backend *be = job->inst->inst_be;
int ret = 0;
+ struct backentry *entry = fi->entry;
if (job->flags & FLAG_UPGRADEDNFORMAT) {
/* Get the entrydn attribute value from deleted attr list */
Slapi_Value *value = NULL;
Slapi_Attr *entryrdn_to_del = NULL;
- entryrdn_to_del = attrlist_remove(&fi->entry->ep_entry->e_deleted_attrs,
+ entryrdn_to_del = attrlist_remove(&entry->ep_entry->e_aux_attrs,
LDBM_ENTRYRDN_STR);
if (entryrdn_to_del) {
/* Delete it. */
@@ -1899,7 +1946,7 @@ foreman_do_entryrdn(ImportJob *job, FifoItem *fi)
} else {
const struct berval *bval =
slapi_value_get_berval((const Slapi_Value *)value);
- ret = entryrdn_index_entry(be, fi->entry, BE_INDEX_DEL, NULL);
+ ret = entryrdn_index_entry(be, entry, BE_INDEX_DEL, NULL);
if (ret) {
import_log_notice(job,
"Error: deleting %s from entrydn index "
@@ -1911,10 +1958,16 @@ foreman_do_entryrdn(ImportJob *job, FifoItem *fi)
slapi_attr_free(&entryrdn_to_del);
}
}
- if ((ret = entryrdn_index_entry(be, fi->entry, BE_INDEX_ADD, NULL)) != 0) {
+ ret = entryrdn_index_entry(be, entry, BE_INDEX_ADD, NULL);
+ if (LDBM_ERROR_FOUND_DUPDN == ret) {
+ import_log_notice(job, "Duplicated DN detected: \"%s\": "
+ "Entry ID: (%d)",
+ slapi_entry_get_dn(entry->ep_entry),
+ entry->ep_id);
+ return ret;
+ } else if (0 != ret) {
import_log_notice(job, "Error writing entryrdn index "
- "(error %d: %s)",
- ret, dblayer_strerror(ret));
+ "(error %d: %s)", ret, dblayer_strerror(ret));
return ret;
}
return 0;
@@ -1991,6 +2044,11 @@ import_foreman(void *param)
/* first, fill in any operational attributes */
/* add_op_attrs wants a pblock for some reason. */
+ if (job->flags & FLAG_UPGRADEDNFORMAT) {
+ /* Upgrade dn format may alter the DIT structure. */
+ /* It requires a special treatment for that. */
+ parent_status = IMPORT_ADD_OP_ATTRS_SAVE_OLD_PID;
+ }
if (add_op_attrs(pb, inst->inst_li, fi->entry, &parent_status) != 0) {
import_log_notice(job, "ERROR: Could not add op attrs to "
"entry ending at line %d of file \"%s\"",
@@ -2037,10 +2095,90 @@ import_foreman(void *param)
} else {
/* insert into the entrydn index */
ret = foreman_do_entrydn(job, fi);
- if (ret == -1)
+ if (ret == -1) {
goto cont; /* skip entry */
+ }
}
- if (ret != 0) {
+ if ((job->flags & FLAG_UPGRADEDNFORMAT) &&
+ (LDBM_ERROR_FOUND_DUPDN == ret)) {
+ /*
+ * Duplicated DN is detected.
+ *
+ * Rename <DN> to nsuniqueid=<uuid>+<DN>
+ * E.g., uid=tuser,dc=example,dc=com ==>
+ * nsuniqueid=<uuid>+uid=tuser,dc=example,dc=com
+ *
+ * Note: FLAG_UPGRADEDNFORMAT only.
+ */
+ Slapi_Attr *orig_entrydn = NULL;
+ Slapi_Attr *new_entrydn = slapi_attr_new();
+ Slapi_Attr *nsuniqueid = NULL;
+ const char *uuidstr = NULL;
+ char *new_dn = NULL;
+ char *orig_dn =
+ slapi_ch_strdup(slapi_entry_get_dn(fi->entry->ep_entry));
+ struct berval *vals[2];
+ struct berval val;
+ int rc = 0;
+ nsuniqueid = attrlist_find(fi->entry->ep_entry->e_attrs,
+ "nsuniqueid");
+ if (nsuniqueid) {
+ Slapi_Value *uival = NULL;
+ rc = slapi_attr_first_value(nsuniqueid, &uival);
+ uuidstr = slapi_value_get_string(uival);
+ } else {
+ import_log_notice(job, "ERROR: Failed to get nsUniqueId "
+ "of the duplicated entry %s; "
+ "Entry ID: %d",
+ orig_dn, fi->entry->ep_id);
+ goto cont;
+ }
+ new_dn = slapi_create_dn_string("nsuniqueid=%s+%s",
+ uuidstr, orig_dn);
+ /* releasing original dn */
+ slapi_sdn_done(&fi->entry->ep_entry->e_sdn);
+ /* setting new dn; pass in */
+ slapi_sdn_init_dn_passin(&fi->entry->ep_entry->e_sdn, new_dn);
+
+ /* Replacing entrydn attribute value */
+ orig_entrydn = attrlist_remove(&fi->entry->ep_entry->e_attrs,
+ "entrydn");
+ /* released in forman_do_entrydn */
+ attrlist_add(&fi->entry->ep_entry->e_aux_attrs, orig_entrydn);
+
+ /* Setting new entrydn attribute value */
+ slapi_attr_init(new_entrydn, "entrydn");
+ valueset_add_string(&new_entrydn->a_present_values,
+ /* new_dn: duped in valueset_add_string */
+ (const char *)new_dn,
+ CSN_TYPE_UNKNOWN, NULL);
+ attrlist_add(&fi->entry->ep_entry->e_attrs, new_entrydn);
+
+ /* Try foreman_do_entry(r)dn, again. */
+ if (entryrdn_get_switch()) { /* subtree-rename: on */
+ /* insert into the entryrdn index */
+ ret = foreman_do_entryrdn(job, fi);
+ } else {
+ /* insert into the entrydn index */
+ ret = foreman_do_entrydn(job, fi);
+ }
+ if (ret) {
+ import_log_notice(job, "ERROR: Failed to rename duplicated "
+ "DN %s to %s; Entry ID: %d",
+ orig_dn, new_dn, fi->entry->ep_id);
+ slapi_ch_free_string(&orig_dn);
+ if (-1 == ret) {
+ goto cont; /* skip entry */
+ } else {
+ goto error;
+ }
+ } else {
+ import_log_notice(job, "WARNING: Duplicated entry %s is "
+ "renamed to %s; Entry ID: %d",
+ orig_dn, new_dn, fi->entry->ep_id);
+ slapi_ch_free_string(&orig_dn);
+ }
+ } else if (0 != ret) {
goto error;
}
}
@@ -2084,17 +2222,14 @@ import_foreman(void *param)
goto error;
}
- if (!(job->flags & FLAG_UPGRADEDNFORMAT) && /* Upgrade dn format mode
- does not need to update
- parentid index */
- !slapi_entry_flag_is_set(fi->entry->ep_entry,
- SLAPI_ENTRY_FLAG_TOMBSTONE)) {
+ if (!slapi_entry_flag_is_set(fi->entry->ep_entry,
+ SLAPI_ENTRY_FLAG_TOMBSTONE)) {
/* parentid index
* (we have to do this here, because the parentID is dependent on
* looking up by entrydn/entryrdn.)
* Only add to the parent index if the entry is not a tombstone.
*/
- ret = foreman_do_parentid(job, fi->entry, parentid_ai);
+ ret = foreman_do_parentid(job, fi, parentid_ai);
if (ret != 0)
goto error;
@@ -2275,7 +2410,7 @@ import_worker(void *param)
Slapi_Value *value = NULL;
const struct berval *bval = NULL;
Slapi_Attr *key_to_del =
- attrlist_remove(&fi->entry->ep_entry->e_deleted_attrs,
+ attrlist_remove(&fi->entry->ep_entry->e_aux_attrs,
info->index_info->name);
if (key_to_del) {