From 86b96278871d8b08f7c6a75379935c2183f6668f Mon Sep 17 00:00:00 2001 From: Noriko Hosoi Date: Aug 25 2015 20:16:10 +0000 Subject: Ticket #48252 - db2index creates index entry from deleted records Bug Description: When an entry is deleted, its indexed attribute values are also removed from each index file. But if the entry is turned to be a tombstone entry, reindexing adds the removed attribute value back to the index file. Fix Description: In the reindexing function ldbm_back_ldbm2index, if the entry is a tombstone entry, it skips reindexing operation unless the target attribute is entryrdn or objectclass. If it is reindexing the objectclass, it indexes just for the key "=nstombstone". https://fedorahosted.org/389/ticket/48252 Reviewed by mreynolds@redhat.com (Thank you, Mark!!) (cherry picked from commit ca4d38dff3bd820af2bf60c9bcc82fd64aac2556) --- diff --git a/ldap/servers/slapd/back-ldbm/ldif2ldbm.c b/ldap/servers/slapd/back-ldbm/ldif2ldbm.c index a1b4a9f..3d07b2e 100644 --- a/ldap/servers/slapd/back-ldbm/ldif2ldbm.c +++ b/ldap/servers/slapd/back-ldbm/ldif2ldbm.c @@ -25,9 +25,12 @@ static char *sourcefile = "ldif2ldbm.c"; -#define DB2INDEX_ANCESTORID 0x1 /* index ancestorid */ -#define DB2INDEX_ENTRYRDN 0x2 /* index entryrdn */ -#define DB2LDIF_ENTRYRDN 0x4 /* export entryrdn */ +#define DB2INDEX_ANCESTORID 0x1 /* index ancestorid */ +#define DB2INDEX_ENTRYRDN 0x2 /* index entryrdn */ +#define DB2LDIF_ENTRYRDN 0x4 /* export entryrdn */ +#define DB2INDEX_OBJECTCLASS 0x10 /* for reindexing "objectclass: nstombstone" */ + +#define LDIF2LDBM_EXTBITS(x) ((x) & 0xf) typedef struct _export_args { struct backentry *ep; @@ -1675,6 +1678,7 @@ ldbm_back_ldbm2index(Slapi_PBlock *pb) struct vlvIndex *vlvip = NULL; back_txn txn; ID suffixid = NOID; /* holds the id of the suffix entry */ + Slapi_Value **nstombstone_vals = NULL; LDAPDebug( LDAP_DEBUG_TRACE, "=> ldbm_back_ldbm2index\n", 0, 0, 0 ); if ( g_get_shutdown() || c_get_shutdown() ) { @@ -1795,7 +1799,7 @@ ldbm_back_ldbm2index(Slapi_PBlock *pb) if (strcasecmp(attrs[i]+1, LDBM_ANCESTORID_STR) == 0) { if (task) { slapi_task_log_notice(task, "%s: Indexing %s", - inst->inst_name, LDBM_ENTRYRDN_STR); + inst->inst_name, LDBM_ANCESTORID_STR); } LDAPDebug2Args(LDAP_DEBUG_ANY, "%s: Indexing %s\n", inst->inst_name, LDBM_ANCESTORID_STR); @@ -1848,6 +1852,9 @@ ldbm_back_ldbm2index(Slapi_PBlock *pb) inst->inst_name, attrs[i] + 1); } } else { + if (strcasecmp(attrs[i]+1, SLAPI_ATTR_OBJECTCLASS) == 0) { + index_ext |= DB2INDEX_OBJECTCLASS; + } charray_add(&indexAttrs, attrs[i]+1); ai->ai_indexmask |= INDEX_OFFLINE; if (task) { @@ -1893,7 +1900,7 @@ ldbm_back_ldbm2index(Slapi_PBlock *pb) * idl composed from the ancestorid list, instead of traversing the * entire database. */ - if (!indexAttrs && !index_ext && pvlv) { + if (!indexAttrs && !LDIF2LDBM_EXTBITS(index_ext) && pvlv) { int err; char **suffix_list = NULL; @@ -2152,11 +2159,13 @@ ldbm_back_ldbm2index(Slapi_PBlock *pb) /* * If this entry is a tombstone, update the 'nstombstonecsn' index */ - if(ep->ep_entry->e_flags & SLAPI_ENTRY_FLAG_TOMBSTONE){ - const CSN *tombstone_csn = NULL; + if (ep->ep_entry->e_flags & SLAPI_ENTRY_FLAG_TOMBSTONE) { + const CSN *tombstone_csn = entry_get_deletion_csn(ep->ep_entry); char deletion_csn_str[CSN_STRSIZE]; - if((tombstone_csn = entry_get_deletion_csn(ep->ep_entry))){ + nstombstone_vals = (Slapi_Value **) slapi_ch_calloc(2, sizeof(Slapi_Value *)); + *nstombstone_vals = slapi_value_new_string(SLAPI_ATTR_VALUE_TOMBSTONE); + if (tombstone_csn) { if (!run_from_cmdline) { rc = dblayer_txn_begin(be, NULL, &txn); if (0 != rc) { @@ -2215,18 +2224,31 @@ ldbm_back_ldbm2index(Slapi_PBlock *pb) /* * Update the attribute indexes */ - if (indexAttrs != NULL) { + if (indexAttrs) { + if (nstombstone_vals && !(index_ext & (DB2INDEX_ENTRYRDN|DB2INDEX_OBJECTCLASS))) { + /* if it is a tombstone entry, just entryrdn or "objectclass: nstombstone" + * need to be reindexed. the to-be-indexed list does not contain them. */ + continue; + } for (i = slapi_entry_first_attr(ep->ep_entry, &attr); i == 0; i = slapi_entry_next_attr(ep->ep_entry, attr, &attr)) { Slapi_Value **svals; slapi_attr_get_type( attr, &type ); for ( j = 0; indexAttrs[j] != NULL; j++ ) { + int is_tombstone_obj = 0; if ( g_get_shutdown() || c_get_shutdown() ) { goto err_out; } - if (slapi_attr_type_cmp(indexAttrs[j], type, - SLAPI_TYPE_CMP_SUBTYPE) == 0 ) { + if (slapi_attr_type_cmp(indexAttrs[j], type, SLAPI_TYPE_CMP_SUBTYPE) == 0) { + if (nstombstone_vals) { + if (!slapi_attr_type_cmp(indexAttrs[j], SLAPI_ATTR_OBJECTCLASS, SLAPI_TYPE_CMP_SUBTYPE)) { + is_tombstone_obj = 1; /* is tombstone && is objectclass. need to index "nstombstone"*/ + } else if (slapi_attr_type_cmp(indexAttrs[j], LDBM_ENTRYRDN_STR, SLAPI_TYPE_CMP_SUBTYPE)) { + /* Entry is a tombstone && this index is not an entryrdn. */ + continue; + } + } svals = attr_get_present_values(attr); if (!run_from_cmdline) { @@ -2250,10 +2272,12 @@ ldbm_back_ldbm2index(Slapi_PBlock *pb) goto err_out; } } - rc = index_addordel_values_sv( - be, indexAttrs[j], svals, - NULL, ep->ep_id, BE_INDEX_ADD, &txn); - if (rc != 0) { + if (is_tombstone_obj) { + rc = index_addordel_values_sv(be, indexAttrs[j], nstombstone_vals, NULL, ep->ep_id, BE_INDEX_ADD, &txn); + } else { + rc = index_addordel_values_sv(be, indexAttrs[j], svals, NULL, ep->ep_id, BE_INDEX_ADD, &txn); + } + if (rc) { LDAPDebug(LDAP_DEBUG_ANY, "%s: ERROR: failed to update index '%s'\n", inst->inst_name, indexAttrs[j], 0); @@ -2299,18 +2323,16 @@ ldbm_back_ldbm2index(Slapi_PBlock *pb) } /* - * Update the Virtual List View indexes + * If it is NOT a tombstone entry, update the Virtual List View indexes. */ - for ( vlvidx = 0; vlvidx < numvlv; vlvidx++ ) { + for (vlvidx = 0; !nstombstone_vals && (vlvidx < numvlv); vlvidx++) { char *ai = "Unknown index"; if ( g_get_shutdown() || c_get_shutdown() ) { goto err_out; } - if(indexAttrs){ - if(indexAttrs[vlvidx]){ - ai = indexAttrs[vlvidx]; - } + if (indexAttrs && indexAttrs[vlvidx]) { + ai = indexAttrs[vlvidx]; } if (!run_from_cmdline) { rc = dblayer_txn_begin(be, NULL, &txn); @@ -2364,7 +2386,7 @@ ldbm_back_ldbm2index(Slapi_PBlock *pb) /* * Update the ancestorid and entryrdn index */ - if (!entryrdn_get_noancestorid() && index_ext & DB2INDEX_ANCESTORID) { + if (!entryrdn_get_noancestorid() && (index_ext & DB2INDEX_ANCESTORID)) { rc = ldbm_ancestorid_index_entry(be, ep, BE_INDEX_ADD, NULL); if (rc != 0) { LDAPDebug(LDAP_DEBUG_ANY,