/* Add or remove stuff from index files */ int bdb_key_change( Backend *be, DB *db, DB_TXN *txn, struct berval *k, ID id, int op ) { int rc; DBT key; Debug( LDAP_DEBUG_TRACE, "=> key_change(%s,%lx)\n", op == SLAP_INDEX_ADD_OP ? "ADD":"DELETE", (long) id, 0 ); DBTzero( &key ); bv2DBT(k,&key); key.ulen = key.size; key.flags = DB_DBT_USERMEM; if (op == SLAP_INDEX_ADD_OP) { /* Add values */ #ifdef BDB_TOOL_IDL_CACHING if ( slapMode & SLAP_TOOL_QUICK ) rc = bdb_tool_idl_add( be, db, txn, &key, id ); else #endif rc = bdb_idl_insert_key( be, db, txn, &key, id ); if ( rc == DB_KEYEXIST ) rc = 0; } else { /* Delete values */ rc = bdb_idl_delete_key( be, db, txn, &key, id ); if ( rc == DB_NOTFOUND ) rc = 0; } Debug( LDAP_DEBUG_TRACE, "<= key_change %d\n", rc, 0, 0 ); return rc; }
int bdb_dn2id_add( Operation *op, DB_TXN *txn, EntryInfo *eip, Entry *e ) { struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private; DB *db = bdb->bi_dn2id->bdi_db; int rc; DBT key, data; ID nid; char *buf; struct berval ptr, pdn; Debug( LDAP_DEBUG_TRACE, "=> bdb_dn2id_add 0x%lx: \"%s\"\n", e->e_id, e->e_ndn, 0 ); assert( e->e_id != NOID ); DBTzero( &key ); key.size = e->e_nname.bv_len + 2; key.ulen = key.size; key.flags = DB_DBT_USERMEM; buf = op->o_tmpalloc( key.size, op->o_tmpmemctx ); key.data = buf; buf[0] = DN_BASE_PREFIX; ptr.bv_val = buf + 1; ptr.bv_len = e->e_nname.bv_len; AC_MEMCPY( ptr.bv_val, e->e_nname.bv_val, e->e_nname.bv_len ); ptr.bv_val[ptr.bv_len] = '\0'; DBTzero( &data ); data.data = &nid; data.size = sizeof( nid ); BDB_ID2DISK( e->e_id, &nid ); /* store it -- don't override */ rc = db->put( db, txn, &key, &data, DB_NOOVERWRITE ); if( rc != 0 ) { char buf[ SLAP_TEXT_BUFLEN ]; snprintf( buf, sizeof( buf ), "%s => bdb_dn2id_add dn=\"%s\" ID=0x%lx", op->o_log_prefix, e->e_name.bv_val, e->e_id ); Debug( LDAP_DEBUG_ANY, "%s: put failed: %s %d\n", buf, db_strerror(rc), rc ); goto done; } #ifndef BDB_MULTIPLE_SUFFIXES if( !be_issuffix( op->o_bd, &ptr )) #endif { buf[0] = DN_SUBTREE_PREFIX; rc = db->put( db, txn, &key, &data, DB_NOOVERWRITE ); if( rc != 0 ) { Debug( LDAP_DEBUG_ANY, "=> bdb_dn2id_add 0x%lx: subtree (%s) put failed: %d\n", e->e_id, ptr.bv_val, rc ); goto done; } #ifdef BDB_MULTIPLE_SUFFIXES if( !be_issuffix( op->o_bd, &ptr )) #endif { dnParent( &ptr, &pdn ); key.size = pdn.bv_len + 2; key.ulen = key.size; pdn.bv_val[-1] = DN_ONE_PREFIX; key.data = pdn.bv_val-1; ptr = pdn; rc = bdb_idl_insert_key( op->o_bd, db, txn, &key, e->e_id ); if( rc != 0 ) { Debug( LDAP_DEBUG_ANY, "=> bdb_dn2id_add 0x%lx: parent (%s) insert failed: %d\n", e->e_id, ptr.bv_val, rc ); goto done; } } #ifndef BDB_MULTIPLE_SUFFIXES while( !be_issuffix( op->o_bd, &ptr )) #else for (;;) #endif { ptr.bv_val[-1] = DN_SUBTREE_PREFIX; rc = bdb_idl_insert_key( op->o_bd, db, txn, &key, e->e_id ); if( rc != 0 ) { Debug( LDAP_DEBUG_ANY, "=> bdb_dn2id_add 0x%lx: subtree (%s) insert failed: %d\n", e->e_id, ptr.bv_val, rc ); break; } #ifdef BDB_MULTIPLE_SUFFIXES if( be_issuffix( op->o_bd, &ptr )) break; #endif dnParent( &ptr, &pdn ); key.size = pdn.bv_len + 2; key.ulen = key.size; key.data = pdn.bv_val - 1; ptr = pdn; } } done: op->o_tmpfree( buf, op->o_tmpmemctx ); Debug( LDAP_DEBUG_TRACE, "<= bdb_dn2id_add 0x%lx: %d\n", e->e_id, rc, 0 ); return rc; }
int bdb_tool_idl_add( BackendDB *be, DB *db, DB_TXN *txn, DBT *key, ID id ) { struct bdb_info *bdb = (struct bdb_info *) be->be_private; bdb_tool_idl_cache *ic, itmp; bdb_tool_idl_cache_entry *ice; int rc; if ( !bdb->bi_idl_cache_max_size ) return bdb_idl_insert_key( be, db, txn, key, id ); DBT2bv( key, &itmp.kstr ); ic = avl_find( (Avlnode *)db->app_private, &itmp, bdb_tool_idl_cmp ); /* No entry yet, create one */ if ( !ic ) { DBC *curs; DBT data; ID nid; int rc; ic = ch_malloc( sizeof( bdb_tool_idl_cache ) + itmp.kstr.bv_len ); ic->kstr.bv_len = itmp.kstr.bv_len; ic->kstr.bv_val = (char *)(ic+1); AC_MEMCPY( ic->kstr.bv_val, itmp.kstr.bv_val, ic->kstr.bv_len ); ic->head = ic->tail = NULL; ic->last = 0; ic->count = 0; avl_insert( (Avlnode **)&db->app_private, ic, bdb_tool_idl_cmp, avl_dup_error ); /* load existing key count here */ rc = db->cursor( db, NULL, &curs, 0 ); if ( rc ) return rc; data.ulen = sizeof( ID ); data.flags = DB_DBT_USERMEM; data.data = &nid; rc = curs->c_get( curs, key, &data, DB_SET ); if ( rc == 0 ) { if ( nid == 0 ) { ic->count = BDB_IDL_DB_SIZE+1; } else { db_recno_t count; curs->c_count( curs, &count, 0 ); ic->count = count; BDB_DISK2ID( &nid, &ic->first ); } } curs->c_close( curs ); } /* are we a range already? */ if ( ic->count > BDB_IDL_DB_SIZE ) { ic->last = id; return 0; /* Are we at the limit, and converting to a range? */ } else if ( ic->count == BDB_IDL_DB_SIZE ) { int n; for ( ice = ic->head, n=0; ice; ice = ice->next, n++ ) /* counting */ ; if ( n ) { ldap_pvt_thread_mutex_lock( &bdb->bi_idl_tree_lrulock ); ic->tail->next = bdb_tool_idl_free_list; bdb_tool_idl_free_list = ic->head; bdb->bi_idl_cache_size -= n; ldap_pvt_thread_mutex_unlock( &bdb->bi_idl_tree_lrulock ); } ic->head = ic->tail = NULL; ic->last = id; ic->count++; return 0; } /* No free block, create that too */ if ( !ic->tail || ( ic->count & (IDBLOCK-1)) == 0) { ice = NULL; ldap_pvt_thread_mutex_lock( &bdb->bi_idl_tree_lrulock ); if ( bdb->bi_idl_cache_size >= bdb->bi_idl_cache_max_size ) { ldap_pvt_thread_mutex_unlock( &bdb->bi_idl_tree_lrulock ); rc = bdb_tool_idl_flush_db( db, ic ); if ( rc ) return rc; avl_insert( (Avlnode **)&db->app_private, ic, bdb_tool_idl_cmp, avl_dup_error ); ldap_pvt_thread_mutex_lock( &bdb->bi_idl_tree_lrulock ); } bdb->bi_idl_cache_size++; if ( bdb_tool_idl_free_list ) { ice = bdb_tool_idl_free_list; bdb_tool_idl_free_list = ice->next; } ldap_pvt_thread_mutex_unlock( &bdb->bi_idl_tree_lrulock ); if ( !ice ) { ice = ch_malloc( sizeof( bdb_tool_idl_cache_entry )); } memset( ice, 0, sizeof( *ice )); if ( !ic->head ) { ic->head = ice; } else { ic->tail->next = ice; } ic->tail = ice; if ( !ic->count ) ic->first = id; } ice = ic->tail; ice->ids[ ic->count & (IDBLOCK-1) ] = id; ic->count++; return 0; }
int bdb_dn2id_add( BackendDB *be, DB_TXN *txn, struct berval *pbv, Entry *e ) { struct bdb_info *bdb = (struct bdb_info *) be->be_private; DB *db = bdb->bi_dn2id->bdi_db; int rc; DBT key, data; char *buf; struct berval ptr, pdn; #ifdef NEW_LOGGING LDAP_LOG ( INDEX, ARGS, "bdb_dn2id_add( \"%s\", 0x%08lx )\n", e->e_ndn, (long) e->e_id, 0 ); #else Debug( LDAP_DEBUG_TRACE, "=> bdb_dn2id_add( \"%s\", 0x%08lx )\n", e->e_ndn, (long) e->e_id, 0 ); #endif assert( e->e_id != NOID ); DBTzero( &key ); key.size = e->e_nname.bv_len + 2; key.ulen = key.size; key.flags = DB_DBT_USERMEM; buf = ch_malloc( key.size ); key.data = buf; buf[0] = DN_BASE_PREFIX; ptr.bv_val = buf + 1; ptr.bv_len = e->e_nname.bv_len; AC_MEMCPY( ptr.bv_val, e->e_nname.bv_val, e->e_nname.bv_len ); ptr.bv_val[ptr.bv_len] = '\0'; DBTzero( &data ); data.data = (char *) &e->e_id; data.size = sizeof( e->e_id ); /* store it -- don't override */ rc = db->put( db, txn, &key, &data, DB_NOOVERWRITE ); if( rc != 0 ) { #ifdef NEW_LOGGING LDAP_LOG ( INDEX, ERR, "bdb_dn2id_add: put failed: %s %d\n", db_strerror(rc), rc, 0 ); #else Debug( LDAP_DEBUG_ANY, "=> bdb_dn2id_add: put failed: %s %d\n", db_strerror(rc), rc, 0 ); #endif goto done; } #ifndef BDB_MULTIPLE_SUFFIXES if( !be_issuffix( be, &ptr )) { #endif buf[0] = DN_SUBTREE_PREFIX; rc = db->put( db, txn, &key, &data, DB_NOOVERWRITE ); if( rc != 0 ) { #ifdef NEW_LOGGING LDAP_LOG ( INDEX, ERR, "=> bdb_dn2id_add: subtree (%s) put failed: %d\n", ptr.bv_val, rc, 0 ); #else Debug( LDAP_DEBUG_ANY, "=> bdb_dn2id_add: subtree (%s) put failed: %d\n", ptr.bv_val, rc, 0 ); #endif goto done; } #ifdef BDB_MULTIPLE_SUFFIXES if( !be_issuffix( be, &ptr )) { #endif dnParent( &ptr, &pdn ); key.size = pdn.bv_len + 2; key.ulen = key.size; pdn.bv_val[-1] = DN_ONE_PREFIX; key.data = pdn.bv_val-1; ptr = pdn; rc = bdb_idl_insert_key( be, db, txn, &key, e->e_id ); if( rc != 0 ) { #ifdef NEW_LOGGING LDAP_LOG ( INDEX, ERR, "=> bdb_dn2id_add: parent (%s) insert failed: %d\n", ptr.bv_val, rc, 0 ); #else Debug( LDAP_DEBUG_ANY, "=> bdb_dn2id_add: parent (%s) insert failed: %d\n", ptr.bv_val, rc, 0 ); #endif goto done; } #ifndef BDB_MULTIPLE_SUFFIXES } while( !be_issuffix( be, &ptr )) { #else for (;;) { #endif ptr.bv_val[-1] = DN_SUBTREE_PREFIX; rc = bdb_idl_insert_key( be, db, txn, &key, e->e_id ); if( rc != 0 ) { #ifdef NEW_LOGGING LDAP_LOG ( INDEX, ERR, "=> bdb_dn2id_add: subtree (%s) insert failed: %d\n", ptr.bv_val, rc, 0 ); #else Debug( LDAP_DEBUG_ANY, "=> bdb_dn2id_add: subtree (%s) insert failed: %d\n", ptr.bv_val, rc, 0 ); #endif break; } #ifdef BDB_MULTIPLE_SUFFIXES if( be_issuffix( be, &ptr )) break; #endif dnParent( &ptr, &pdn ); key.size = pdn.bv_len + 2; key.ulen = key.size; key.data = pdn.bv_val - 1; ptr = pdn; } #ifdef BDB_MULTIPLE_SUFFIXES } #endif done: ch_free( buf ); #ifdef NEW_LOGGING LDAP_LOG ( INDEX, RESULTS, "<= bdb_dn2id_add: %d\n", rc, 0, 0 ); #else Debug( LDAP_DEBUG_TRACE, "<= bdb_dn2id_add: %d\n", rc, 0, 0 ); #endif return rc; } int bdb_dn2id_delete( BackendDB *be, DB_TXN *txn, char *pdnc, Entry *e ) { struct bdb_info *bdb = (struct bdb_info *) be->be_private; DB *db = bdb->bi_dn2id->bdi_db; int rc; DBT key; char *buf; struct berval pdn, ptr; #ifdef NEW_LOGGING LDAP_LOG ( INDEX, ARGS, "=> bdb_dn2id_delete ( \"%s\", 0x%08lx )\n", e->e_ndn, e->e_id, 0); #else Debug( LDAP_DEBUG_TRACE, "=> bdb_dn2id_delete( \"%s\", 0x%08lx )\n", e->e_ndn, e->e_id, 0 ); #endif DBTzero( &key ); key.size = e->e_nname.bv_len + 2; buf = ch_malloc( key.size ); key.data = buf; key.flags = DB_DBT_USERMEM; buf[0] = DN_BASE_PREFIX; ptr.bv_val = buf+1; ptr.bv_len = e->e_nname.bv_len; AC_MEMCPY( ptr.bv_val, e->e_nname.bv_val, e->e_nname.bv_len ); ptr.bv_val[ptr.bv_len] = '\0'; /* delete it */ rc = db->del( db, txn, &key, 0 ); if( rc != 0 ) { #ifdef NEW_LOGGING LDAP_LOG ( INDEX, ERR, "=> bdb_dn2id_delete: delete failed: %s %d\n", db_strerror(rc), rc, 0 ); #else Debug( LDAP_DEBUG_ANY, "=> bdb_dn2id_delete: delete failed: %s %d\n", db_strerror(rc), rc, 0 ); #endif goto done; } #ifndef BDB_MULTIPLE_SUFFIXES if( !be_issuffix( be, &ptr )) { #endif buf[0] = DN_SUBTREE_PREFIX; rc = db->del( db, txn, &key, 0 ); if( rc != 0 ) { #ifdef NEW_LOGGING LDAP_LOG ( INDEX, ERR, "=> bdb_dn2id_delete: subtree (%s) delete failed: %d\n", ptr.bv_val, rc, 0 ); #else Debug( LDAP_DEBUG_ANY, "=> bdb_dn2id_delete: subtree (%s) delete failed: %d\n", ptr.bv_val, rc, 0 ); #endif goto done; } #ifdef BDB_MULTIPLE_SUFFIXES if( !be_issuffix( be, &ptr )) { #endif dnParent( &ptr, &pdn ); key.size = pdn.bv_len + 2; key.ulen = key.size; pdn.bv_val[-1] = DN_ONE_PREFIX; key.data = pdn.bv_val - 1; ptr = pdn; rc = bdb_idl_delete_key( be, db, txn, &key, e->e_id ); if( rc != 0 ) { #ifdef NEW_LOGGING LDAP_LOG ( INDEX, ERR, "=> bdb_dn2id_delete: parent (%s) delete failed: %d\n", ptr.bv_val, rc, 0 ); #else Debug( LDAP_DEBUG_ANY, "=> bdb_dn2id_delete: parent (%s) delete failed: %d\n", ptr.bv_val, rc, 0 ); #endif goto done; } #ifndef BDB_MULTIPLE_SUFFIXES } while( !be_issuffix( be, &ptr )) { #else for (;;) { #endif ptr.bv_val[-1] = DN_SUBTREE_PREFIX; rc = bdb_idl_delete_key( be, db, txn, &key, e->e_id ); if( rc != 0 ) { #ifdef NEW_LOGGING LDAP_LOG ( INDEX, ERR, "=> bdb_dn2id_delete: subtree (%s) delete failed: %d\n", ptr.bv_val, rc, 0 ); #else Debug( LDAP_DEBUG_ANY, "=> bdb_dn2id_delete: subtree (%s) delete failed: %d\n", ptr.bv_val, rc, 0 ); #endif goto done; } #ifdef BDB_MULTIPLE_SUFFIXES if( be_issuffix( be, &ptr )) break; #endif dnParent( &ptr, &pdn ); key.size = pdn.bv_len + 2; key.ulen = key.size; key.data = pdn.bv_val - 1; ptr = pdn; } #ifdef BDB_MULTIPLE_SUFFIXES } #endif done: ch_free( buf ); #ifdef NEW_LOGGING LDAP_LOG ( INDEX, RESULTS, "<= bdb_dn2id_delete %d\n", rc, 0, 0 ); #else Debug( LDAP_DEBUG_TRACE, "<= bdb_dn2id_delete %d\n", rc, 0, 0 ); #endif return rc; } int bdb_dn2id( BackendDB *be, DB_TXN *txn, struct berval *dn, ID *id, int flags ) { int rc; DBT key, data; struct bdb_info *bdb = (struct bdb_info *) be->be_private; DB *db = bdb->bi_dn2id->bdi_db; #ifdef NEW_LOGGING LDAP_LOG ( INDEX, ARGS, "=> bdb_dn2id( \"%s\" )\n", dn->bv_val, 0, 0 ); #else Debug( LDAP_DEBUG_TRACE, "=> bdb_dn2id( \"%s\" )\n", dn->bv_val, 0, 0 ); #endif assert (id); *id = bdb_cache_find_entry_ndn2id(be, &bdb->bi_cache, dn); if (*id != NOID) { return 0; } DBTzero( &key ); key.size = dn->bv_len + 2; key.data = ch_malloc( key.size ); ((char *)key.data)[0] = DN_BASE_PREFIX; AC_MEMCPY( &((char *)key.data)[1], dn->bv_val, key.size - 1 ); /* store the ID */ DBTzero( &data ); data.data = id; data.ulen = sizeof(ID); data.flags = DB_DBT_USERMEM; /* fetch it */ rc = db->get( db, txn, &key, &data, bdb->bi_db_opflags | flags); if( rc != 0 ) { #ifdef NEW_LOGGING LDAP_LOG ( INDEX, ERR, "<= bdb_dn2id: get failed %s (%d)\n", db_strerror(rc), rc, 0 ); #else Debug( LDAP_DEBUG_TRACE, "<= bdb_dn2id: get failed: %s (%d)\n", db_strerror( rc ), rc, 0 ); #endif } else { #ifdef NEW_LOGGING LDAP_LOG ( INDEX, RESULTS, "<= bdb_dn2id: got id=0x%08lx\n", *id, 0, 0 ); #else Debug( LDAP_DEBUG_TRACE, "<= bdb_dn2id: got id=0x%08lx\n", *id, 0, 0 ); #endif } ch_free( key.data ); return rc; } int bdb_dn2id_matched( BackendDB *be, DB_TXN *txn, struct berval *in, ID *id, ID *id2, int flags ) { int rc; DBT key, data; struct bdb_info *bdb = (struct bdb_info *) be->be_private; DB *db = bdb->bi_dn2id->bdi_db; char *buf; struct berval dn; ID cached_id; #ifdef NEW_LOGGING LDAP_LOG ( INDEX, ARGS, "=> bdb_dn2id_matched( \"%s\" )\n", in->bv_val, 0, 0 ); #else Debug( LDAP_DEBUG_TRACE, "=> bdb_dn2id_matched( \"%s\" )\n", in->bv_val, 0, 0 ); #endif DBTzero( &key ); key.size = in->bv_len + 2; buf = ch_malloc( key.size ); key.data = buf; dn.bv_val = buf+1; dn.bv_len = key.size - 2; AC_MEMCPY( dn.bv_val, in->bv_val, key.size - 1 ); /* store the ID */ DBTzero( &data ); data.data = id; data.ulen = sizeof(ID); data.flags = DB_DBT_USERMEM; while(1) { dn.bv_val[-1] = DN_BASE_PREFIX; *id = NOID; /* lookup cache */ cached_id = bdb_cache_find_entry_ndn2id(be, &bdb->bi_cache, &dn); if (cached_id != NOID) { rc = 0; *id = cached_id; if ( dn.bv_val != buf+1 ) { *id2 = *id; } break; } else { /* fetch it */ rc = db->get(db, txn, &key, &data, bdb->bi_db_opflags | flags ); } if( rc == DB_NOTFOUND ) { struct berval pdn; if ( ! be_issuffix( be, &dn ) ) { dnParent( &dn, &pdn ); } else { #ifdef NEW_LOGGING LDAP_LOG ( INDEX, DETAIL1, "<= bdb_dn2id_matched: no match\n", 0, 0, 0 ); #else Debug( LDAP_DEBUG_TRACE, "<= bdb_dn2id_matched: no match\n", 0, 0, 0 ); #endif break; } key.size = pdn.bv_len + 2; dn = pdn; key.data = pdn.bv_val - 1; } else if ( rc == 0 ) { if( data.size != sizeof( ID ) ) { #ifdef NEW_LOGGING LDAP_LOG ( INDEX, DETAIL1, "<= bdb_dn2id_matched: get size mismatch:" "expected %ld, got %ld\n", (long) sizeof(ID), (long) data.size, 0 ); #else Debug( LDAP_DEBUG_ANY, "<= bdb_dn2id_matched: get size mismatch: " "expected %ld, got %ld\n", (long) sizeof(ID), (long) data.size, 0 ); #endif } if( dn.bv_val != buf+1 ) { *id2 = *id; } #ifdef NEW_LOGGING LDAP_LOG ( INDEX, DETAIL1, "<= bdb_dn2id_matched: id=0x%08lx: %s %s\n", (long) *id, *id2 == 0 ? "entry" : "matched", dn.bv_val ); #else Debug( LDAP_DEBUG_TRACE, "<= bdb_dn2id_matched: id=0x%08lx: %s %s\n", (long) *id, *id2 == 0 ? "entry" : "matched", dn.bv_val ); #endif break; } else { #ifdef NEW_LOGGING LDAP_LOG ( INDEX, ERR, "<= bdb_dn2id_matched: get failed: %s (%d)\n", db_strerror(rc), rc, 0 ); #else Debug( LDAP_DEBUG_ANY, "<= bdb_dn2id_matched: get failed: %s (%d)\n", db_strerror(rc), rc, 0 ); #endif break; } } ch_free( buf ); return rc; }