]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/back-bdb/dn2id.c
ITS#4040 move initialization
[openldap] / servers / slapd / back-bdb / dn2id.c
index 69f80dd2f63da8b6e7573ae62278117cff58b5e9..5131fd1a9fe20df68e6d9375533b4cce5f00d5ce 100644 (file)
@@ -381,10 +381,7 @@ bdb_dn2idl(
 }
 
 #else  /* BDB_HIER */
-/* Experimental management routines for a hierarchically structured database.
- *
- * Unsupported! Use at your own risk!
- * -- Howard Chu, Symas Corp. 2003.
+/* Management routines for a hierarchically structured database.
  *
  * Instead of a ldbm-style dn2id database, we use a hierarchical one. Each
  * entry in this database is a struct diskNode, keyed by entryID and with
@@ -402,9 +399,9 @@ bdb_dn2idl(
  */
 typedef struct diskNode {
        unsigned char nrdnlen[2];
-       unsigned char nrdn[1];
-       unsigned char rdn[1];
-       unsigned char entryID[sizeof(ID)];
+       char nrdn[1];
+       char rdn[1];                        /* variable placement */
+       unsigned char entryID[sizeof(ID)];  /* variable placement */
 } diskNode;
 
 /* This function constructs a full DN for a given entry.
@@ -516,7 +513,7 @@ hdb_dn2id_add(
         * will fail harmlessly.
         */
        if ( eip->bei_id == 0 ) {
-               diskNode dummy = {0};
+               diskNode dummy = {{0, 0}, "", "", ""};
                data.data = &dummy;
                data.size = sizeof(diskNode);
                data.flags = DB_DBT_USERMEM;
@@ -555,8 +552,9 @@ hdb_dn2id_delete(
        DBT             key, data;
        DBC     *cursor;
        diskNode *d;
-       int rc, nrlen;
+       int rc;
        ID      nid;
+       unsigned char dlen[2];
 
        DBTzero(&key);
        key.size = sizeof(ID);
@@ -586,13 +584,16 @@ hdb_dn2id_delete(
        d = op->o_tmpalloc( data.size, op->o_tmpmemctx );
        d->nrdnlen[1] = BEI(e)->bei_nrdn.bv_len & 0xff;
        d->nrdnlen[0] = (BEI(e)->bei_nrdn.bv_len >> 8) | 0x80;
+       dlen[0] = d->nrdnlen[0];
+       dlen[1] = d->nrdnlen[1];
        strcpy( d->nrdn, BEI(e)->bei_nrdn.bv_val );
        data.data = d;
 
        /* Delete our ID from the parent's list */
        rc = cursor->c_get( cursor, &key, &data, DB_GET_BOTH_RANGE );
        if ( rc == 0 ) {
-               if ( !strcmp( d->nrdn, BEI(e)->bei_nrdn.bv_val ))
+               if ( dlen[1] == d->nrdnlen[1] && dlen[0] == d->nrdnlen[0] &&
+                       !strcmp( d->nrdn, BEI(e)->bei_nrdn.bv_val ))
                        rc = cursor->c_del( cursor, 0 );
                else
                        rc = DB_NOTFOUND;
@@ -630,7 +631,7 @@ hdb_dn2id(
        diskNode *d;
        char    *ptr;
        unsigned char dlen[2];
-       ID idp;
+       ID idp, parentID;
 
        nrlen = dn_rdnlen( op->o_bd, in );
        if (!nrlen) nrlen = in->bv_len;
@@ -640,7 +641,8 @@ hdb_dn2id(
        key.data = &idp;
        key.ulen = sizeof(ID);
        key.flags = DB_DBT_USERMEM;
-       BDB_ID2DISK( ei->bei_parent->bei_id, &idp );
+       parentID = ( ei->bei_parent != NULL ) ? ei->bei_parent->bei_id : 0;
+       BDB_ID2DISK( parentID, &idp );
 
        DBTzero(&data);
        data.size = sizeof(diskNode) + nrlen - sizeof(ID) - 1;
@@ -666,12 +668,12 @@ hdb_dn2id(
                rc = DB_NOTFOUND;
        }
        if ( rc == 0 ) {
-               ptr = data.data + data.size - sizeof(ID);
+               ptr = (char *) data.data + data.size - sizeof(ID);
                BDB_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->bei_dkids ) {
+               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
@@ -701,7 +703,6 @@ hdb_dn2id_parent(
        int             rc = 0;
        diskNode *d;
        char    *ptr;
-       unsigned char *pt2;
        ID      nid;
 
        DBTzero(&key);
@@ -727,7 +728,7 @@ hdb_dn2id_parent(
                        rc = LDAP_OTHER;
                } else {
                        db_recno_t dkids;
-                       ptr = data.data + data.size - sizeof(ID);
+                       ptr = (char *) data.data + data.size - sizeof(ID);
                        BDB_DISK2ID( ptr, idp );
                        ei->bei_nrdn.bv_len = (d->nrdnlen[0] << 8) | d->nrdnlen[1];
                        ber_str2bv( d->nrdn, ei->bei_nrdn.bv_len, 1, &ei->bei_nrdn );
@@ -817,12 +818,13 @@ struct dn2id_cookie {
        ID dbuf;
        ID *ids;
        void *ptr;
-       ID tmp[BDB_IDL_UM_SIZE];
+       ID *tmp;
        ID *buf;
        DBT key;
        DBT data;
        DBC *dbc;
        Operation *op;
+       int need_sort;
 };
 
 static int
@@ -950,15 +952,18 @@ hdb_dn2idl_internal(
        }
 
 saveit:
+       if ( !BDB_IDL_IS_RANGE( cx->tmp ) && cx->tmp[0] > 3 )
+               bdb_idl_sort( cx->tmp, cx->buf );
        if ( cx->bdb->bi_idl_cache_max_size ) {
                cx->key.data = &cx->id;
                bdb_idl_cache_put( cx->bdb, cx->db, &cx->key, cx->tmp, cx->rc );
        }
-       ;
+
 gotit:
        if ( !BDB_IDL_IS_ZERO( cx->tmp )) {
                if ( cx->prefix == DN_SUBTREE_PREFIX ) {
                        bdb_idl_append( cx->ids, cx->tmp );
+                       cx->need_sort = 1;
                        if ( !(cx->ei->bei_state & CACHE_ENTRY_NO_GRANDKIDS)) {
                                ID *save, idcurs;
                                EntryInfo *ei = cx->ei;
@@ -1021,8 +1026,10 @@ hdb_dn2idl(
        cx.prefix = (op->ors_scope == LDAP_SCOPE_ONELEVEL) ?
                DN_ONE_PREFIX : DN_SUBTREE_PREFIX;
        cx.ids = ids;
-       cx.buf = stack;
+       cx.tmp = stack;
+       cx.buf = stack + BDB_IDL_UM_SIZE;
        cx.op = op;
+       cx.need_sort = 0;
 
        BDB_IDL_ZERO( ids );
        if ( cx.prefix == DN_SUBTREE_PREFIX ) {
@@ -1037,8 +1044,8 @@ hdb_dn2idl(
        DBTzero(&cx.data);
 
        hdb_dn2idl_internal(&cx);
-       if ( !BDB_IDL_IS_ZERO( ids ) && !BDB_IDL_IS_RANGE( ids ))
-               bdb_idl_sort( ids );
+       if ( cx.need_sort && !BDB_IDL_IS_RANGE( cx.ids ) && cx.ids[0] > 3 )
+               bdb_idl_sort( cx.ids, cx.tmp );
 
        return cx.rc;
 }