From c4f99a5ddcd06ea4daaaa41ef3bcd5919c1e0549 Mon Sep 17 00:00:00 2001 From: Howard Chu Date: Thu, 18 Aug 2011 20:29:01 -0700 Subject: [PATCH] dn2id fixes, slapadd working --- servers/slapd/back-mdb/dn2entry.c | 6 +- servers/slapd/back-mdb/dn2id.c | 114 ++++++++++++++++------------- servers/slapd/back-mdb/init.c | 3 + servers/slapd/back-mdb/libmdb | 2 +- servers/slapd/back-mdb/nextid.c | 2 +- servers/slapd/back-mdb/proto-mdb.h | 3 +- servers/slapd/back-mdb/tools.c | 42 ++++++----- 7 files changed, 94 insertions(+), 78 deletions(-) diff --git a/servers/slapd/back-mdb/dn2entry.c b/servers/slapd/back-mdb/dn2entry.c index 448593c553..e2da3dca9a 100644 --- a/servers/slapd/back-mdb/dn2entry.c +++ b/servers/slapd/back-mdb/dn2entry.c @@ -43,13 +43,9 @@ mdb_dn2entry( *e = NULL; - rc = mdb_dn2id( op, tid, dn, &id ); + rc = mdb_dn2id( op, tid, dn, &id, matched ); if ( rc ) { *e = NULL; - if ( matched && rc == MDB_NOTFOUND ) { - /* Get the parent's DN */ - mdb_id2name( op, tid, id, matched, NULL ); - } } else { rc = mdb_id2entry( op, tid, id, e ); } diff --git a/servers/slapd/back-mdb/dn2id.c b/servers/slapd/back-mdb/dn2id.c index 6f53ec3edd..b18ab47a45 100644 --- a/servers/slapd/back-mdb/dn2id.c +++ b/servers/slapd/back-mdb/dn2id.c @@ -253,87 +253,99 @@ func_leave: return rc; } - +/* return last found ID in *id if no match */ int mdb_dn2id( Operation *op, MDB_txn *txn, struct berval *in, - ID *id ) + ID *id, + struct berval *matched ) { struct mdb_info *mdb = (struct mdb_info *) op->o_bd->be_private; + MDB_cursor *cursor; MDB_dbi dbi = mdb->mi_dn2id->mdi_dbi; MDB_val key, data; int rc = 0, nrlen; diskNode *d; char *ptr; unsigned char dlen[2]; - ID idp, parentID; + ID pid, nid; + struct berval tmp; -#if 0 Debug( LDAP_DEBUG_TRACE, "=> mdb_dn2id(\"%s\")\n", in->bv_val, 0, 0 ); - nrlen = dn_rdnlen( op->o_bd, in ); - if (!nrlen) nrlen = in->bv_len; + if ( !in->bv_len ) { + *id = 0; + nid = 0; + goto done; + } - DBTzero(&key); - key.size = sizeof(ID); - key.data = &idp; - key.ulen = sizeof(ID); - key.flags = DB_DBT_USERMEM; - parentID = ( ei->bei_parent != NULL ) ? ei->bei_parent->bei_id : 0; - MDB_ID2DISK( parentID, &idp ); + tmp = *in; - DBTzero(&data); - data.size = sizeof(diskNode) + nrlen - sizeof(ID) - 1; - data.ulen = data.size * 3; - data.dlen = data.ulen; - data.flags = DB_DBT_USERMEM | DB_DBT_PARTIAL; + nrlen = tmp.bv_len - op->o_bd->be_nsuffix[0].bv_len; + tmp.bv_val += nrlen; + tmp.bv_len = op->o_bd->be_nsuffix[0].bv_len; + nid = 0; + key.mv_size = sizeof(ID); - rc = db->cursor( db, txn, cursor, mdb->bi_db_opflags ); + rc = mdb_cursor_open( txn, dbi, &cursor ); if ( rc ) return rc; - d = op->o_tmpalloc( data.size * 3, op->o_tmpmemctx ); - d->nrdnlen[1] = nrlen & 0xff; - d->nrdnlen[0] = (nrlen >> 8) | 0x80; - dlen[0] = d->nrdnlen[0]; - dlen[1] = d->nrdnlen[1]; - ptr = lutil_strncopy( d->nrdn, in->bv_val, nrlen ); - *ptr = '\0'; - data.data = d; - - rc = (*cursor)->c_get( *cursor, &key, &data, DB_GET_BOTH_RANGE ); - if ( rc == 0 && (dlen[1] != d->nrdnlen[1] || dlen[0] != d->nrdnlen[0] || - strncmp( d->nrdn, in->bv_val, nrlen ))) { - rc = DB_NOTFOUND; - } - if ( rc == 0 ) { - ptr = (char *) data.data + data.size - sizeof(ID); - MDB_DISK2ID( ptr, &ei->bei_id ); - ei->bei_rdn.bv_len = data.size - sizeof(diskNode) - nrlen; - ptr = d->nrdn + nrlen + 1; - ber_str2bv( ptr, ei->bei_rdn.bv_len, 1, &ei->bei_rdn ); - if ( ei->bei_parent != NULL && !ei->bei_parent->bei_dkids ) { - db_recno_t dkids; - /* How many children does the parent have? */ - /* FIXME: do we need to lock the parent - * entryinfo? Seems safe... - */ - (*cursor)->c_count( *cursor, &dkids, 0 ); - ei->bei_parent->bei_dkids = dkids; + for (;;) { + key.mv_data = &pid; + pid = nid; + + data.mv_size = sizeof(diskNode) + tmp.bv_len; + d = op->o_tmpalloc( data.mv_size, op->o_tmpmemctx ); + d->nrdnlen[1] = tmp.bv_len & 0xff; + d->nrdnlen[0] = (tmp.bv_len >> 8) | 0x80; + ptr = lutil_strncopy( d->nrdn, tmp.bv_val, tmp.bv_len ); + *ptr = '\0'; + data.mv_data = d; + rc = mdb_cursor_get( cursor, &key, &data, MDB_GET_BOTH ); + if ( rc == MDB_NOTFOUND ) { + if ( matched ) { + int len; + matched->bv_val = tmp.bv_val + tmp.bv_len + 1; + len = in->bv_len - ( matched->bv_val - in->bv_val ); + if ( len <= 0 ) { + BER_BVZERO( matched ); + } else { + matched->bv_len = len; + } + } + } + op->o_tmpfree( d, op->o_tmpmemctx ); + if ( rc ) { + mdb_cursor_close( cursor ); + break; + } + ptr = (char *) data.mv_data + data.mv_size - sizeof(ID); + memcpy( &nid, ptr, sizeof(ID)); + if ( tmp.bv_val > in->bv_val ) { + for (ptr = tmp.bv_val - 2; ptr > in->bv_val && + !DN_SEPARATOR(*ptr); ptr--) /* empty */; + if ( ptr >= in->bv_val ) { + if (DN_SEPARATOR(*ptr)) ptr++; + tmp.bv_len = tmp.bv_val - ptr - 1; + tmp.bv_val = ptr; + } + } else { + break; } } + *id = nid; - op->o_tmpfree( d, op->o_tmpmemctx ); +done: if( rc != 0 ) { Debug( LDAP_DEBUG_TRACE, "<= mdb_dn2id: get failed: %s (%d)\n", - db_strerror( rc ), rc, 0 ); + mdb_strerror( rc ), rc, 0 ); } else { Debug( LDAP_DEBUG_TRACE, "<= mdb_dn2id: got id=0x%lx\n", - ei->bei_id, 0, 0 ); + nid, 0, 0 ); } -#endif return rc; } diff --git a/servers/slapd/back-mdb/init.c b/servers/slapd/back-mdb/init.c index f3dbe6751b..e51b34bd62 100644 --- a/servers/slapd/back-mdb/init.c +++ b/servers/slapd/back-mdb/init.c @@ -217,6 +217,9 @@ mdb_db_open( BackendDB *be, ConfigReply *cr ) goto fail; } + if ( i == MDB_DN2ID ) + mdb_set_dupsort( txn, db->mdi_dbi, mdb_dup_compare ); + db->mdi_name = mdmi_databases[i]; mdb->mi_databases[i] = db; } diff --git a/servers/slapd/back-mdb/libmdb b/servers/slapd/back-mdb/libmdb index 319a976a50..aa43616762 160000 --- a/servers/slapd/back-mdb/libmdb +++ b/servers/slapd/back-mdb/libmdb @@ -1 +1 @@ -Subproject commit 319a976a50058efc6232eb240c929850ed583671 +Subproject commit aa436167624c27c74dc8559a9e0b40d318bdba86 diff --git a/servers/slapd/back-mdb/nextid.c b/servers/slapd/back-mdb/nextid.c index b62ad15c03..e98ca0cf46 100644 --- a/servers/slapd/back-mdb/nextid.c +++ b/servers/slapd/back-mdb/nextid.c @@ -43,7 +43,7 @@ int mdb_next_id( BackendDB *be, MDB_txn *tid, ID *out ) *out = 1; break; case 0: - memcpy( key.mv_data, &id, sizeof( id )); + memcpy( &id, key.mv_data, sizeof( id )); *out = ++id; break; diff --git a/servers/slapd/back-mdb/proto-mdb.h b/servers/slapd/back-mdb/proto-mdb.h index 6b62482f2d..2942ff3bdd 100644 --- a/servers/slapd/back-mdb/proto-mdb.h +++ b/servers/slapd/back-mdb/proto-mdb.h @@ -74,7 +74,8 @@ int mdb_dn2id( Operation *op, MDB_txn *txn, struct berval *dn, - ID *id ); + ID *id, + struct berval *matched ); int mdb_dn2id_add( Operation *op, diff --git a/servers/slapd/back-mdb/tools.c b/servers/slapd/back-mdb/tools.c index 4b9e6e73a9..1d8a19379e 100644 --- a/servers/slapd/back-mdb/tools.c +++ b/servers/slapd/back-mdb/tools.c @@ -245,7 +245,7 @@ ID mdb_tool_dn2id_get( op.o_tmpmemctx = NULL; op.o_tmpmfuncs = &ch_mfuncs; - rc = mdb_dn2id( &op, txn, dn, &id ); + rc = mdb_dn2id( &op, txn, dn, &id, NULL ); if ( rc == MDB_NOTFOUND ) return NOID; @@ -344,8 +344,8 @@ static int mdb_tool_next_id( { struct berval dn = e->e_name; struct berval ndn = e->e_nname; - struct berval pdn, npdn; - ID id, pid; + struct berval pdn, npdn, matched; + ID id, pid = 0; int rc; if (ndn.bv_len == 0) { @@ -353,26 +353,30 @@ static int mdb_tool_next_id( return 0; } - rc = mdb_dn2id( op, tid, &ndn, &id ); + rc = mdb_dn2id( op, tid, &ndn, &id, &matched ); if ( rc == MDB_NOTFOUND ) { if ( !be_issuffix( op->o_bd, &ndn ) ) { ID eid = e->e_id; - dnParent( &dn, &pdn ); dnParent( &ndn, &npdn ); - e->e_name = pdn; - e->e_nname = npdn; - rc = mdb_tool_next_id( op, tid, e, text, 1 ); - e->e_name = dn; - e->e_nname = ndn; - if ( rc ) { - return rc; - } - /* If parent didn't exist, it was created just now - * and its ID is now in e->e_id. Make sure the current - * entry gets added under the new parent ID. - */ - if ( eid != e->e_id ) { - pid = e->e_id; + if ( matched.bv_len != npdn.bv_len ) { + dnParent( &dn, &pdn ); + e->e_name = pdn; + e->e_nname = npdn; + rc = mdb_tool_next_id( op, tid, e, text, 1 ); + e->e_name = dn; + e->e_nname = ndn; + if ( rc ) { + return rc; + } + /* If parent didn't exist, it was created just now + * and its ID is now in e->e_id. Make sure the current + * entry gets added under the new parent ID. + */ + if ( eid != e->e_id ) { + pid = e->e_id; + } + } else { + pid = id; } } rc = mdb_next_id( op->o_bd, tid, &e->e_id ); -- 2.39.2