Diff for /servers/slapd/back-bdb/dn2id.c between versions 1.106 and 1.106.2.14

version 1.106, 2004/12/08 19:55:35 version 1.106.2.14, 2006/01/03 22:16:16
Line 1 Line 1
 /* dn2id.c - routines to deal with the dn2id index */  /* dn2id.c - routines to deal with the dn2id index */
 /* $OpenLDAP: pkg/ldap/servers/slapd/back-bdb/dn2id.c,v 1.105 2004/12/06 06:28:47 hyc Exp $ */  /* $OpenLDAP: pkg/ldap/servers/slapd/back-bdb/dn2id.c,v 1.106.2.13 2005/12/20 23:00:11 kurt Exp $ */
 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.  /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
  *   *
  * Copyright 2000-2004 The OpenLDAP Foundation.   * Copyright 2000-2006 The OpenLDAP Foundation.
  * All rights reserved.   * All rights reserved.
  *   *
  * Redistribution and use in source and binary forms, with or without   * Redistribution and use in source and binary forms, with or without
Line 178  bdb_dn2id_delete( Line 178  bdb_dn2id_delete(
 #endif  #endif
         {          {
                 buf[0] = DN_SUBTREE_PREFIX;                  buf[0] = DN_SUBTREE_PREFIX;
                 rc = db->del( db, txn, &key, 0 );                  rc = bdb_idl_delete_key( op->o_bd, db, txn, &key, e->e_id );
                 if( rc != 0 ) {                  if( rc != 0 ) {
                         Debug( LDAP_DEBUG_ANY,                          Debug( LDAP_DEBUG_ANY,
                         "=> bdb_dn2id_delete: subtree (%s) delete failed: %d\n",                          "=> bdb_dn2id_delete: subtree (%s) delete failed: %d\n",
Line 361  bdb_dn2idl( Line 361  bdb_dn2idl(
         ((char *)key.data)[0] = prefix;          ((char *)key.data)[0] = prefix;
         AC_MEMCPY( &((char *)key.data)[1], e->e_nname.bv_val, key.size - 1 );          AC_MEMCPY( &((char *)key.data)[1], e->e_nname.bv_val, key.size - 1 );
   
           BDB_IDL_ZERO( ids );
         rc = bdb_idl_fetch_key( op->o_bd, db, NULL, &key, ids, NULL, 0 );          rc = bdb_idl_fetch_key( op->o_bd, db, NULL, &key, ids, NULL, 0 );
   
         if( rc != 0 ) {          if( rc != 0 ) {
Line 380  bdb_dn2idl( Line 381  bdb_dn2idl(
 }  }
   
 #else   /* BDB_HIER */  #else   /* BDB_HIER */
 /* Experimental management routines for a hierarchically structured database.  /* Management routines for a hierarchically structured database.
  *  
  * Unsupported! Use at your own risk!  
  * -- Howard Chu, Symas Corp. 2003.  
  *   *
  * Instead of a ldbm-style dn2id database, we use a hierarchical one. Each   * 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   * entry in this database is a struct diskNode, keyed by entryID and with
Line 391  bdb_dn2idl( Line 389  bdb_dn2idl(
  * a B-Tree with sorted duplicates to store all the children of a node under   * a B-Tree with sorted duplicates to store all the children of a node under
  * the same key. Also, the first item under the key contains the entry's own   * the same key. Also, the first item under the key contains the entry's own
  * rdn and the ID of the node's parent, to allow bottom-up tree traversal as   * rdn and the ID of the node's parent, to allow bottom-up tree traversal as
  * well as top-down. To keep this info first in the list, the nrdnlen is set   * well as top-down. To keep this info first in the list, the high bit of all
  * to the negative of its value.   * subsequent nrdnlen's is always set. This means we can only accomodate
    * RDNs up to length 32767, but that's fine since full DNs are already
    * restricted to 8192.
  *   *
  * The diskNode is a variable length structure. This definition is not   * The diskNode is a variable length structure. This definition is not
  * directly usable for in-memory manipulation.   * directly usable for in-memory manipulation.
  */   */
 typedef struct diskNode {  typedef struct diskNode {
         ID entryID;          unsigned char nrdnlen[2];
         short nrdnlen;  
         char nrdn[1];          char nrdn[1];
         char rdn[1];          char rdn[1];                        /* variable placement */
           unsigned char entryID[sizeof(ID)];  /* variable placement */
 } diskNode;  } diskNode;
   
 /* Sort function for the sorted duplicate data items of a dn2id key.  
  * Sorts based on normalized RDN, in length order.  
  */  
 int  
 hdb_dup_compare(  
         DB *db,   
         const DBT *usrkey,  
         const DBT *curkey )  
 {  
         signed char *u = (signed char *)&(((diskNode *)(usrkey->data))->nrdnlen);  
         signed char *c = (signed char *)&(((diskNode *)(curkey->data))->nrdnlen);  
         int rc, i;  
   
         /* data is not aligned, cannot compare directly */  
 #ifdef WORDS_BIGENDIAN  
         for( i = 0; i < (int)sizeof(short); i++)  
 #else  
         for( i = sizeof(short)-1; i >= 0; i--)  
 #endif  
         {  
                 rc = u[i] - c[i];  
                 if( rc ) return rc;  
         }  
         return strcmp( u+sizeof(short), c+sizeof(short) );  
 }  
   
 /* This function constructs a full DN for a given entry.  /* This function constructs a full DN for a given entry.
  */   */
 int hdb_fix_dn(  int hdb_fix_dn(
Line 441  int hdb_fix_dn( Line 415  int hdb_fix_dn(
         char *ptr, *nptr;          char *ptr, *nptr;
         int max = 0;          int max = 0;
   
           if ( !e->e_id )
                   return 0;
   
         /* count length of all DN components */          /* count length of all DN components */
         for ( ei = BEI(e); ei && ei->bei_id; ei=ei->bei_parent ) {          for ( ei = BEI(e); ei && ei->bei_id; ei=ei->bei_parent ) {
                 rlen += ei->bei_rdn.bv_len + 1;                  rlen += ei->bei_rdn.bv_len + 1;
Line 497  hdb_dn2id_add( Line 474  hdb_dn2id_add(
         struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;          struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
         DB *db = bdb->bi_dn2id->bdi_db;          DB *db = bdb->bi_dn2id->bdi_db;
         DBT             key, data;          DBT             key, data;
           ID              nid;
         int             rc, rlen, nrlen;          int             rc, rlen, nrlen;
         diskNode *d;          diskNode *d;
         char *ptr;          char *ptr;
Line 510  hdb_dn2id_add( Line 488  hdb_dn2id_add(
         }          }
   
         d = op->o_tmpalloc(sizeof(diskNode) + rlen + nrlen, op->o_tmpmemctx);          d = op->o_tmpalloc(sizeof(diskNode) + rlen + nrlen, op->o_tmpmemctx);
         d->entryID = e->e_id;          d->nrdnlen[1] = nrlen & 0xff;
         d->nrdnlen = nrlen;          d->nrdnlen[0] = (nrlen >> 8) | 0x80;
         ptr = lutil_strncopy( d->nrdn, e->e_nname.bv_val, nrlen );          ptr = lutil_strncopy( d->nrdn, e->e_nname.bv_val, nrlen );
         *ptr++ = '\0';          *ptr++ = '\0';
         ptr = lutil_strncopy( ptr, e->e_name.bv_val, rlen );          ptr = lutil_strncopy( ptr, e->e_name.bv_val, rlen );
         *ptr = '\0';          *ptr++ = '\0';
           BDB_ID2DISK( e->e_id, ptr );
   
         DBTzero(&key);          DBTzero(&key);
         DBTzero(&data);          DBTzero(&data);
         key.data = &eip->bei_id;  
         key.size = sizeof(ID);          key.size = sizeof(ID);
         key.flags = DB_DBT_USERMEM;          key.flags = DB_DBT_USERMEM;
           BDB_ID2DISK( eip->bei_id, &nid );
   
           key.data = &nid;
   
         /* Need to make dummy root node once. Subsequent attempts          /* Need to make dummy root node once. Subsequent attempts
          * will fail harmlessly.           * will fail harmlessly.
          */           */
         if ( eip->bei_id == 0 ) {          if ( eip->bei_id == 0 ) {
                 diskNode dummy = {0};                  diskNode dummy = {{0, 0}, "", "", ""};
                 data.data = &dummy;                  data.data = &dummy;
                 data.size = sizeof(diskNode);                  data.size = sizeof(diskNode);
                 data.flags = DB_DBT_USERMEM;                  data.flags = DB_DBT_USERMEM;
Line 535  hdb_dn2id_add( Line 516  hdb_dn2id_add(
                 db->put( db, txn, &key, &data, DB_NODUPDATA );                  db->put( db, txn, &key, &data, DB_NODUPDATA );
         }          }
   
         if ( bdb->bi_idl_cache_size ) {  
                 bdb_idl_cache_del( bdb, db, &key );  
         }  
         data.data = d;          data.data = d;
         data.size = sizeof(diskNode) + rlen + nrlen;          data.size = sizeof(diskNode) + rlen + nrlen;
         data.flags = DB_DBT_USERMEM;          data.flags = DB_DBT_USERMEM;
Line 545  hdb_dn2id_add( Line 523  hdb_dn2id_add(
         rc = db->put( db, txn, &key, &data, DB_NODUPDATA );          rc = db->put( db, txn, &key, &data, DB_NODUPDATA );
   
         if (rc == 0) {          if (rc == 0) {
                 key.data = &e->e_id;                  BDB_ID2DISK( e->e_id, &nid );
                 d->entryID = eip->bei_id;                  BDB_ID2DISK( eip->bei_id, ptr );
                 d->nrdnlen = 0 - nrlen;                  d->nrdnlen[0] ^= 0x80;
   
                 rc = db->put( db, txn, &key, &data, DB_NODUPDATA );                  rc = db->put( db, txn, &key, &data, DB_NODUPDATA );
         }          }
   
           /* Update all parents' IDL cache entries */
           if ( rc == 0 && bdb->bi_idl_cache_size ) {
                   ID tmp[2];
                   char *ptr = ((char *)&tmp[1])-1;
                   key.data = ptr;
                   key.size = sizeof(ID)+1;
                   tmp[1] = eip->bei_id;
                   *ptr = DN_ONE_PREFIX;
                   bdb_idl_cache_add_id( bdb, db, &key, e->e_id );
                   *ptr = DN_SUBTREE_PREFIX;
                   for (; eip && eip->bei_parent->bei_id; eip = eip->bei_parent) {
                           tmp[1] = eip->bei_id;
                           bdb_idl_cache_add_id( bdb, db, &key, e->e_id );
                   }
           }
         op->o_tmpfree( d, op->o_tmpmemctx );          op->o_tmpfree( d, op->o_tmpmemctx );
   
         return rc;          return rc;
Line 569  hdb_dn2id_delete( Line 562  hdb_dn2id_delete(
         DBT             key, data;          DBT             key, data;
         DBC     *cursor;          DBC     *cursor;
         diskNode *d;          diskNode *d;
         int rc, nrlen;          int rc;
           ID      nid;
           unsigned char dlen[2];
   
         DBTzero(&key);          DBTzero(&key);
         key.size = sizeof(ID);          key.size = sizeof(ID);
         key.ulen = key.size;          key.ulen = key.size;
         key.data = &eip->bei_id;  
         key.flags = DB_DBT_USERMEM;          key.flags = DB_DBT_USERMEM;
           BDB_ID2DISK( eip->bei_id, &nid );
   
         DBTzero(&data);          DBTzero(&data);
         data.size = sizeof(diskNode) + BEI(e)->bei_nrdn.bv_len;          data.size = sizeof(diskNode) + BEI(e)->bei_nrdn.bv_len - sizeof(ID) - 1;
         data.ulen = data.size;          data.ulen = data.size;
         data.dlen = data.size;          data.dlen = data.size;
         data.flags = DB_DBT_USERMEM | DB_DBT_PARTIAL;          data.flags = DB_DBT_USERMEM | DB_DBT_PARTIAL;
   
         if ( bdb->bi_idl_cache_size ) {          key.data = &nid;
                 bdb_idl_cache_del( bdb, db, &key );  
         }  
         rc = db->cursor( db, txn, &cursor, bdb->bi_db_opflags );          rc = db->cursor( db, txn, &cursor, bdb->bi_db_opflags );
         if ( rc ) return rc;          if ( rc ) return rc;
   
         d = op->o_tmpalloc( data.size, op->o_tmpmemctx );          d = op->o_tmpalloc( data.size, op->o_tmpmemctx );
         d->entryID = e->e_id;          d->nrdnlen[1] = BEI(e)->bei_nrdn.bv_len & 0xff;
         d->nrdnlen = BEI(e)->bei_nrdn.bv_len;          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 );          strcpy( d->nrdn, BEI(e)->bei_nrdn.bv_val );
         data.data = d;          data.data = d;
   
         /* Delete our ID from the parent's list */          /* Delete our ID from the parent's list */
         rc = cursor->c_get( cursor, &key, &data, DB_GET_BOTH | DB_RMW );          rc = cursor->c_get( cursor, &key, &data, DB_GET_BOTH_RANGE );
         if ( rc == 0 )          if ( rc == 0 ) {
                 rc = cursor->c_del( cursor, 0 );                  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;
           }
   
         /* Delete our ID from the tree. With sorted duplicates, this          /* Delete our ID from the tree. With sorted duplicates, this
          * will leave any child nodes still hanging around. This is OK           * will leave any child nodes still hanging around. This is OK
          * for modrdn, which will add our info back in later.           * for modrdn, which will add our info back in later.
          */           */
         if ( rc == 0 ) {          if ( rc == 0 ) {
                 key.data = &e->e_id;                  BDB_ID2DISK( e->e_id, &nid );
                 rc = cursor->c_get( cursor, &key, &data, DB_SET | DB_RMW );                  rc = cursor->c_get( cursor, &key, &data, DB_SET );
                 if ( rc == 0 )                  if ( rc == 0 )
                         rc = cursor->c_del( cursor, 0 );                          rc = cursor->c_del( cursor, 0 );
         }          }
         cursor->c_close( cursor );          cursor->c_close( cursor );
         op->o_tmpfree( d, op->o_tmpmemctx );          op->o_tmpfree( d, op->o_tmpmemctx );
   
           /* Delete IDL cache entries */
           if ( rc == 0 && bdb->bi_idl_cache_size ) {
                   ID tmp[2];
                   char *ptr = ((char *)&tmp[1])-1;
                   key.data = ptr;
                   key.size = sizeof(ID)+1;
                   tmp[1] = eip->bei_id;
                   *ptr = DN_ONE_PREFIX;
                   bdb_idl_cache_del_id( bdb, db, &key, e->e_id );
                   *ptr = DN_SUBTREE_PREFIX;
                   for (; eip && eip->bei_parent->bei_id; eip = eip->bei_parent) {
                           tmp[1] = eip->bei_id;
                           bdb_idl_cache_del_id( bdb, db, &key, e->e_id );
                   }
           }
         return rc;          return rc;
 }  }
   
Line 631  hdb_dn2id( Line 646  hdb_dn2id(
         int             rc = 0, nrlen;          int             rc = 0, nrlen;
         diskNode *d;          diskNode *d;
         char    *ptr;          char    *ptr;
         ID idp = ei->bei_parent->bei_id;          unsigned char dlen[2];
           ID idp, parentID;
   
         nrlen = dn_rdnlen( op->o_bd, in );          nrlen = dn_rdnlen( op->o_bd, in );
         if (!nrlen) nrlen = in->bv_len;          if (!nrlen) nrlen = in->bv_len;
Line 641  hdb_dn2id( Line 657  hdb_dn2id(
         key.data = &idp;          key.data = &idp;
         key.ulen = sizeof(ID);          key.ulen = sizeof(ID);
         key.flags = DB_DBT_USERMEM;          key.flags = DB_DBT_USERMEM;
           parentID = ( ei->bei_parent != NULL ) ? ei->bei_parent->bei_id : 0;
           BDB_ID2DISK( parentID, &idp );
   
         DBTzero(&data);          DBTzero(&data);
         data.size = sizeof(diskNode) + nrlen;          data.size = sizeof(diskNode) + nrlen - sizeof(ID) - 1;
         data.ulen = data.size * 3;          data.ulen = data.size * 3;
         data.flags = DB_DBT_USERMEM;          data.dlen = data.ulen;
           data.flags = DB_DBT_USERMEM | DB_DBT_PARTIAL;
   
         rc = db->cursor( db, txn, &cursor, bdb->bi_db_opflags );          rc = db->cursor( db, txn, &cursor, bdb->bi_db_opflags );
         if ( rc ) return rc;          if ( rc ) return rc;
   
         d = op->o_tmpalloc( data.size * 3, op->o_tmpmemctx );          d = op->o_tmpalloc( data.size * 3, op->o_tmpmemctx );
         d->nrdnlen = nrlen;          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 = lutil_strncopy( d->nrdn, in->bv_val, nrlen );
         *ptr = '\0';          *ptr = '\0';
         data.data = d;          data.data = d;
   
         rc = cursor->c_get( cursor, &key, &data, DB_GET_BOTH );          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 ) {          if ( rc == 0 ) {
                 ei->bei_id = d->entryID;                  ptr = (char *) data.data + data.size - sizeof(ID);
                   BDB_DISK2ID( ptr, &ei->bei_id );
                 ei->bei_rdn.bv_len = data.size - sizeof(diskNode) - nrlen;                  ei->bei_rdn.bv_len = data.size - sizeof(diskNode) - nrlen;
                 ptr = d->nrdn + nrlen + 1;                  ptr = d->nrdn + nrlen + 1;
                 ber_str2bv( ptr, ei->bei_rdn.bv_len, 1, &ei->bei_rdn );                  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;                          db_recno_t dkids;
                         /* How many children does the parent have? */                          /* How many children does the parent have? */
                         /* FIXME: do we need to lock the parent                          /* FIXME: do we need to lock the parent
Line 682  int Line 709  int
 hdb_dn2id_parent(  hdb_dn2id_parent(
         Operation *op,          Operation *op,
         DB_TXN *txn,          DB_TXN *txn,
           u_int32_t       locker,
         EntryInfo *ei,          EntryInfo *ei,
         ID *idp )          ID *idp )
 {  {
Line 692  hdb_dn2id_parent( Line 720  hdb_dn2id_parent(
         int             rc = 0;          int             rc = 0;
         diskNode *d;          diskNode *d;
         char    *ptr;          char    *ptr;
         unsigned char *pt2;          ID      nid;
   
         DBTzero(&key);          DBTzero(&key);
         key.size = sizeof(ID);          key.size = sizeof(ID);
         key.data = &ei->bei_id;          key.data = &nid;
         key.ulen = sizeof(ID);          key.ulen = sizeof(ID);
         key.flags = DB_DBT_USERMEM;          key.flags = DB_DBT_USERMEM;
           BDB_ID2DISK( ei->bei_id, &nid );
   
         DBTzero(&data);          DBTzero(&data);
         data.flags = DB_DBT_USERMEM;          data.flags = DB_DBT_USERMEM;
   
         rc = db->cursor( db, txn, &cursor, bdb->bi_db_opflags );          rc = db->cursor( db, txn, &cursor, bdb->bi_db_opflags );
         if ( rc ) return rc;          if ( rc ) return rc;
           if ( !txn && locker ) {
                   cursor->locker = locker;
           }
   
         data.ulen = sizeof(diskNode) + (SLAP_LDAPDN_MAXLEN * 2);          data.ulen = sizeof(diskNode) + (SLAP_LDAPDN_MAXLEN * 2);
         d = op->o_tmpalloc( data.ulen, op->o_tmpmemctx );          d = op->o_tmpalloc( data.ulen, op->o_tmpmemctx );
Line 712  hdb_dn2id_parent( Line 744  hdb_dn2id_parent(
   
         rc = cursor->c_get( cursor, &key, &data, DB_SET );          rc = cursor->c_get( cursor, &key, &data, DB_SET );
         if ( rc == 0 ) {          if ( rc == 0 ) {
                 if (d->nrdnlen >= 0) {                  if (d->nrdnlen[0] & 0x80) {
                         rc = LDAP_OTHER;                          rc = LDAP_OTHER;
                 } else {                  } else {
                         db_recno_t dkids;                          db_recno_t dkids;
                         *idp = d->entryID;                          ptr = (char *) data.data + data.size - sizeof(ID);
                         ei->bei_nrdn.bv_len = 0 - d->nrdnlen;                          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 );                          ber_str2bv( d->nrdn, ei->bei_nrdn.bv_len, 1, &ei->bei_nrdn );
                         ei->bei_rdn.bv_len = data.size - sizeof(diskNode) -                          ei->bei_rdn.bv_len = data.size - sizeof(diskNode) -
                                 ei->bei_nrdn.bv_len;                                  ei->bei_nrdn.bv_len;
Line 751  hdb_dn2id_children( Line 784  hdb_dn2id_children(
         key.size = sizeof(ID);          key.size = sizeof(ID);
         key.data = &e->e_id;          key.data = &e->e_id;
         key.flags = DB_DBT_USERMEM;          key.flags = DB_DBT_USERMEM;
           BDB_ID2DISK( e->e_id, &id );
   
           /* IDL cache is in host byte order */
         if ( bdb->bi_idl_cache_size ) {          if ( bdb->bi_idl_cache_size ) {
                 rc = bdb_idl_cache_get( bdb, db, &key, NULL );                  rc = bdb_idl_cache_get( bdb, db, &key, NULL );
                 if ( rc != LDAP_NO_SUCH_OBJECT ) {                  if ( rc != LDAP_NO_SUCH_OBJECT ) {
                         return rc;                          return rc;
                 }                  }
         }          }
   
           key.data = &id;
         DBTzero(&data);          DBTzero(&data);
         data.data = &d;          data.data = &d;
         data.ulen = sizeof(d);          data.ulen = sizeof(d);
Line 792  hdb_dn2id_children( Line 829  hdb_dn2id_children(
   
 struct dn2id_cookie {  struct dn2id_cookie {
         struct bdb_info *bdb;          struct bdb_info *bdb;
         DB *db;          Operation *op;
         int prefix;  
         int rc;  
         EntryInfo *ei;          EntryInfo *ei;
         ID id;  
         ID dbuf;  
         ID *ids;          ID *ids;
         void *ptr;          ID *tmp;
         ID tmp[BDB_IDL_DB_SIZE];  
         ID *buf;          ID *buf;
           DB *db;
           DBC *dbc;
         DBT key;          DBT key;
         DBT data;          DBT data;
         DBC *dbc;          ID dbuf;
         Operation *op;          ID id;
           ID nid;
           int rc;
           int depth;
           char need_sort;
           char prefix;
 };  };
   
 static int  static int
Line 816  apply_func( Line 855  apply_func(
         EntryInfo *ei = data;          EntryInfo *ei = data;
         ID *idl = arg;          ID *idl = arg;
   
         bdb_idl_insert( idl, ei->bei_id );          bdb_idl_append_one( idl, ei->bei_id );
         return 0;          return 0;
 }  }
   
Line 825  hdb_dn2idl_internal( Line 864  hdb_dn2idl_internal(
         struct dn2id_cookie *cx          struct dn2id_cookie *cx
 )  )
 {  {
           BDB_IDL_ZERO( cx->tmp );
   
         if ( cx->bdb->bi_idl_cache_size ) {          if ( cx->bdb->bi_idl_cache_size ) {
                 cx->rc = bdb_idl_cache_get(cx->bdb, cx->db, &cx->key, cx->tmp);                  char *ptr = ((char *)&cx->id)-1;
                 if ( cx->rc == DB_NOTFOUND ) {  
                         return cx->rc;                  cx->key.data = ptr;
                   cx->key.size = sizeof(ID)+1;
                   if ( cx->prefix == DN_SUBTREE_PREFIX ) {
                           ID *ids = cx->depth ? cx->tmp : cx->ids;
                           *ptr = cx->prefix;
                           cx->rc = bdb_idl_cache_get(cx->bdb, cx->db, &cx->key, ids);
                           if ( cx->rc == LDAP_SUCCESS ) {
                                   if ( cx->depth ) {
                                           bdb_idl_append( cx->ids, cx->tmp );
                                           cx->need_sort = 1;
                                   }
                                   return cx->rc;
                           }
                 }                  }
                   *ptr = DN_ONE_PREFIX;
                   cx->rc = bdb_idl_cache_get(cx->bdb, cx->db, &cx->key, cx->tmp);
                 if ( cx->rc == LDAP_SUCCESS ) {                  if ( cx->rc == LDAP_SUCCESS ) {
                         goto gotit;                          goto gotit;
                 }                  }
         }                  if ( cx->rc == DB_NOTFOUND ) {
         BDB_IDL_ZERO( cx->tmp );                          return cx->rc;
   
         if ( !cx->ei ) {  
                 cx->ei = bdb_cache_find_info( cx->bdb, cx->id );  
                 if ( !cx->ei ) {  
                         cx->rc = DB_NOTFOUND;  
                         goto saveit;  
                 }                  }
         }          }
   
Line 854  hdb_dn2idl_internal( Line 903  hdb_dn2idl_internal(
                 db_recno_t dkids = cx->ei->bei_dkids;                  db_recno_t dkids = cx->ei->bei_dkids;
                 ei.bei_parent = cx->ei;                  ei.bei_parent = cx->ei;
   
                   /* Only one thread should load the cache */
                   while ( cx->ei->bei_state & CACHE_ENTRY_ONELEVEL ) {
                           bdb_cache_entryinfo_unlock( cx->ei );
                           ldap_pvt_thread_yield();
                           bdb_cache_entryinfo_lock( cx->ei );
                           if ( cx->ei->bei_ckids+1 == cx->ei->bei_dkids ) {
                                   goto synced;
                           }
                   }
   
                   cx->ei->bei_state |= CACHE_ENTRY_ONELEVEL;
   
                 bdb_cache_entryinfo_unlock( cx->ei );                  bdb_cache_entryinfo_unlock( cx->ei );
   
                 cx->rc = cx->db->cursor( cx->db, NULL, &cx->dbc,                  cx->rc = cx->db->cursor( cx->db, NULL, &cx->dbc,
                         cx->bdb->bi_db_opflags );                          cx->bdb->bi_db_opflags );
                 if ( cx->rc ) return cx->rc;                  if ( cx->rc )
                           goto done_one;
   
                 cx->data.data = &cx->dbuf;                  cx->data.data = &cx->dbuf;
                 cx->data.ulen = sizeof(ID);                  cx->data.ulen = sizeof(ID);
Line 866  hdb_dn2idl_internal( Line 928  hdb_dn2idl_internal(
                 cx->data.flags = DB_DBT_USERMEM | DB_DBT_PARTIAL;                  cx->data.flags = DB_DBT_USERMEM | DB_DBT_PARTIAL;
   
                 /* The first item holds the parent ID. Ignore it. */                  /* The first item holds the parent ID. Ignore it. */
                   cx->key.data = &cx->nid;
                   cx->key.size = sizeof(ID);
                 cx->rc = cx->dbc->c_get( cx->dbc, &cx->key, &cx->data, DB_SET );                  cx->rc = cx->dbc->c_get( cx->dbc, &cx->key, &cx->data, DB_SET );
                 if ( cx->rc ) {                  if ( cx->rc ) {
                         cx->dbc->c_close( cx->dbc );                          cx->dbc->c_close( cx->dbc );
                         if ( cx->rc == DB_NOTFOUND ) goto saveit;                          goto done_one;
                         return cx->rc;  
                 }                  }
   
                 /* If the on-disk count is zero we've never checked it.                  /* If the on-disk count is zero we've never checked it.
Line 885  hdb_dn2idl_internal( Line 948  hdb_dn2idl_internal(
                 cx->data.ulen = BDB_IDL_UM_SIZE * sizeof(ID);                  cx->data.ulen = BDB_IDL_UM_SIZE * sizeof(ID);
                 cx->data.flags = DB_DBT_USERMEM;                  cx->data.flags = DB_DBT_USERMEM;
   
                 /* Fetch the rest of the IDs in a loop... */                  if ( dkids > 1 ) {
                 while ( (cx->rc = cx->dbc->c_get( cx->dbc, &cx->key, &cx->data,                          /* Fetch the rest of the IDs in a loop... */
                         DB_MULTIPLE | DB_NEXT_DUP )) == 0 ) {                          while ( (cx->rc = cx->dbc->c_get( cx->dbc, &cx->key, &cx->data,
                         u_int8_t *j;                                  DB_MULTIPLE | DB_NEXT_DUP )) == 0 ) {
                         size_t len;                                  u_int8_t *j;
                         DB_MULTIPLE_INIT( cx->ptr, &cx->data );                                  size_t len;
                         while (cx->ptr) {                                  void *ptr;
                                 DB_MULTIPLE_NEXT( cx->ptr, &cx->data, j, len );                                  DB_MULTIPLE_INIT( ptr, &cx->data );
                                 if (j) {                                  while (ptr) {
                                         EntryInfo *ei2;                                          DB_MULTIPLE_NEXT( ptr, &cx->data, j, len );
                                         diskNode *d = (diskNode *)j;                                          if (j) {
                                         short nrlen;                                                  EntryInfo *ei2;
                                                   diskNode *d = (diskNode *)j;
                                         AC_MEMCPY( &ei.bei_id, &d->entryID, sizeof(ID) );                                                  short nrlen;
                                         AC_MEMCPY( &nrlen, &d->nrdnlen, sizeof(d->nrdnlen) );  
                                         ei.bei_nrdn.bv_len = nrlen;                                                  BDB_DISK2ID( j + len - sizeof(ID), &ei.bei_id );
                                         /* nrdn/rdn are set in-place.                                                  nrlen = ((d->nrdnlen[0] ^ 0x80) << 8) | d->nrdnlen[1];
                                          * hdb_cache_load will copy them as needed                                                  ei.bei_nrdn.bv_len = nrlen;
                                          */                                                  /* nrdn/rdn are set in-place.
                                         ei.bei_nrdn.bv_val = d->nrdn;                                                   * hdb_cache_load will copy them as needed
                                         ei.bei_rdn.bv_len = len - sizeof(diskNode)                                                   */
                                                 - ei.bei_nrdn.bv_len;                                                  ei.bei_nrdn.bv_val = d->nrdn;
                                         ei.bei_rdn.bv_val = d->nrdn + ei.bei_nrdn.bv_len + 1;                                                  ei.bei_rdn.bv_len = len - sizeof(diskNode)
                                         bdb_idl_insert( cx->tmp, ei.bei_id );                                                          - ei.bei_nrdn.bv_len;
                                         hdb_cache_load( cx->bdb, &ei, &ei2 );                                                  ei.bei_rdn.bv_val = d->nrdn + ei.bei_nrdn.bv_len + 1;
                                                   bdb_idl_append_one( cx->tmp, ei.bei_id );
                                                   hdb_cache_load( cx->bdb, &ei, &ei2 );
                                           }
                                 }                                  }
                         }                          }
                 }                  }
   
                 cx->rc = cx->dbc->c_close( cx->dbc );                  cx->rc = cx->dbc->c_close( cx->dbc );
   done_one:
                   bdb_cache_entryinfo_lock( cx->ei );
                   cx->ei->bei_state ^= CACHE_ENTRY_ONELEVEL;
                   bdb_cache_entryinfo_unlock( cx->ei );
                   if ( cx->rc )
                           return cx->rc;
   
         } else {          } else {
                 /* The in-memory cache is in sync with the on-disk data.                  /* The in-memory cache is in sync with the on-disk data.
                  * do we have any kids?                   * do we have any kids?
                  */                   */
   synced:
                 cx->rc = 0;                  cx->rc = 0;
                 if ( cx->ei->bei_ckids > 0 ) {                  if ( cx->ei->bei_ckids > 0 ) {
                         /* Walk the kids tree; order is irrelevant since bdb_idl_insert                          /* Walk the kids tree; order is irrelevant since bdb_idl_sort
                          * will insert in sorted order.                           * will sort it later.
                          */                           */
                         avl_apply( cx->ei->bei_kids, apply_func,                          avl_apply( cx->ei->bei_kids, apply_func,
                                 cx->tmp, -1, AVL_POSTORDER );                                  cx->tmp, -1, AVL_POSTORDER );
Line 929  hdb_dn2idl_internal( Line 1004  hdb_dn2idl_internal(
                 bdb_cache_entryinfo_unlock( cx->ei );                  bdb_cache_entryinfo_unlock( cx->ei );
         }          }
   
 saveit:          if ( !BDB_IDL_IS_RANGE( cx->tmp ) && cx->tmp[0] > 3 )
         if ( cx->bdb->bi_idl_cache_max_size ) {                  bdb_idl_sort( cx->tmp, cx->buf );
           if ( cx->bdb->bi_idl_cache_max_size && !BDB_IDL_IS_ZERO( cx->tmp )) {
                   char *ptr = ((char *)&cx->id)-1;
                   cx->key.data = ptr;
                   cx->key.size = sizeof(ID)+1;
                   *ptr = DN_ONE_PREFIX;
                 bdb_idl_cache_put( cx->bdb, cx->db, &cx->key, cx->tmp, cx->rc );                  bdb_idl_cache_put( cx->bdb, cx->db, &cx->key, cx->tmp, cx->rc );
         }          }
         ;  
 gotit:  gotit:
         if ( !BDB_IDL_IS_ZERO( cx->tmp )) {          if ( !BDB_IDL_IS_ZERO( cx->tmp )) {
                 if ( cx->prefix == DN_SUBTREE_PREFIX ) {                  if ( cx->prefix == DN_SUBTREE_PREFIX ) {
                         if (cx->ei->bei_state & CACHE_ENTRY_NO_GRANDKIDS) {                          bdb_idl_append( cx->ids, cx->tmp );
                                 bdb_idl_union( cx->ids, cx->tmp );                          cx->need_sort = 1;
                         } else {                          if ( !(cx->ei->bei_state & CACHE_ENTRY_NO_GRANDKIDS)) {
                                 ID *save, idcurs;                                  ID *save, idcurs;
                                 EntryInfo *ei = cx->ei;                                  EntryInfo *ei = cx->ei;
                                 int nokids = 1;                                  int nokids = 1;
                                 save = cx->op->o_tmpalloc( BDB_IDL_SIZEOF( cx->tmp ),                                  save = cx->op->o_tmpalloc( BDB_IDL_SIZEOF( cx->tmp ),
                                         cx->op->o_tmpmemctx );                                          cx->op->o_tmpmemctx );
                                 BDB_IDL_CPY( save, cx->tmp );                                  BDB_IDL_CPY( save, cx->tmp );
                                 bdb_idl_union( cx->ids, cx->tmp );  
   
                                 idcurs = 0;                                  idcurs = 0;
                                   cx->depth++;
                                 for ( cx->id = bdb_idl_first( save, &idcurs );                                  for ( cx->id = bdb_idl_first( save, &idcurs );
                                         cx->id != NOID;                                          cx->id != NOID;
                                         cx->id = bdb_idl_next( save, &idcurs )) {                                          cx->id = bdb_idl_next( save, &idcurs )) {
                                         cx->ei = NULL;                                          cx->ei = bdb_cache_find_info( cx->bdb, cx->id );
                                           if ( !cx->ei ||
                                                   ( cx->ei->bei_state & CACHE_ENTRY_NO_KIDS ))
                                                   continue;
   
                                           BDB_ID2DISK( cx->id, &cx->nid );
                                         hdb_dn2idl_internal( cx );                                          hdb_dn2idl_internal( cx );
                                         if ( !BDB_IDL_IS_ZERO( cx->tmp ))                                          if ( !BDB_IDL_IS_ZERO( cx->tmp ))
                                                 nokids = 0;                                                  nokids = 0;
                                 }                                  }
                                   cx->depth--;
                                 cx->op->o_tmpfree( save, cx->op->o_tmpmemctx );                                  cx->op->o_tmpfree( save, cx->op->o_tmpmemctx );
                                 if ( nokids ) ei->bei_state |= CACHE_ENTRY_NO_GRANDKIDS;                                  if ( nokids ) ei->bei_state |= CACHE_ENTRY_NO_GRANDKIDS;
                         }                          }
Line 994  hdb_dn2idl( Line 1080  hdb_dn2idl(
 #endif  #endif
   
         cx.id = e->e_id;          cx.id = e->e_id;
           BDB_ID2DISK( cx.id, &cx.nid );
         cx.ei = e->e_id ? BEI(e) : &bdb->bi_cache.c_dntree;          cx.ei = e->e_id ? BEI(e) : &bdb->bi_cache.c_dntree;
         cx.bdb = bdb;          cx.bdb = bdb;
         cx.db = cx.bdb->bi_dn2id->bdi_db;          cx.db = cx.bdb->bi_dn2id->bdi_db;
         cx.prefix = op->ors_scope == LDAP_SCOPE_ONELEVEL          cx.prefix = (op->ors_scope == LDAP_SCOPE_ONELEVEL) ?
                 ? DN_ONE_PREFIX : DN_SUBTREE_PREFIX;                  DN_ONE_PREFIX : DN_SUBTREE_PREFIX;
         cx.ids = ids;          cx.ids = ids;
         cx.buf = stack;          cx.tmp = stack;
           cx.buf = stack + BDB_IDL_UM_SIZE;
         cx.op = op;          cx.op = op;
           cx.need_sort = 0;
           cx.depth = 0;
   
         BDB_IDL_ZERO( ids );  
         if ( cx.prefix == DN_SUBTREE_PREFIX ) {          if ( cx.prefix == DN_SUBTREE_PREFIX ) {
                 bdb_idl_insert( ids, cx.id );                  ids[0] = 1;
                   ids[1] = cx.id;
           } else {
                   BDB_IDL_ZERO( ids );
         }          }
           if ( cx.ei->bei_state & CACHE_ENTRY_NO_KIDS )
                   return LDAP_SUCCESS;
   
         DBTzero(&cx.key);          DBTzero(&cx.key);
         cx.key.data = &cx.id;  
         cx.key.ulen = sizeof(ID);          cx.key.ulen = sizeof(ID);
         cx.key.size = sizeof(ID);          cx.key.size = sizeof(ID);
         cx.key.flags = DB_DBT_USERMEM;          cx.key.flags = DB_DBT_USERMEM;
   
         DBTzero(&cx.data);          DBTzero(&cx.data);
   
         return hdb_dn2idl_internal(&cx);          hdb_dn2idl_internal(&cx);
           if ( cx.need_sort ) {
                   char *ptr = ((char *)&cx.id)-1;
                   if ( !BDB_IDL_IS_RANGE( cx.ids ) && cx.ids[0] > 3 ) 
                           bdb_idl_sort( cx.ids, cx.tmp );
                   cx.key.data = ptr;
                   cx.key.size = sizeof(ID)+1;
                   *ptr = cx.prefix;
                   cx.id = e->e_id;
                   bdb_idl_cache_put( cx.bdb, cx.db, &cx.key, cx.ids, cx.rc );
           }
   
           if ( cx.rc == DB_NOTFOUND )
                   cx.rc = LDAP_SUCCESS;
   
           return cx.rc;
 }  }
 #endif  /* BDB_HIER */  #endif  /* BDB_HIER */

Removed from v.1.106  
changed lines
  Added in v.1.106.2.14


______________
© Copyright 1998-2020, OpenLDAP Foundation, info@OpenLDAP.org