diff options
Diffstat (limited to 'ldap/servers/slapd/back-ldbm/import-threads.c')
-rw-r--r-- | ldap/servers/slapd/back-ldbm/import-threads.c | 213 |
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) { |