X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=servers%2Fslapd%2Fback-bdb%2Fidl.c;h=5d7f321857e43aca864e412703ecded9c8b110ee;hb=3972e13fc3de47d46a1d81655fac9b1baaae5622;hp=d793462291f6dcb3757c4439ebccaf90adc184eb;hpb=6939c531700652491f4be4688c6a1f35a1ab8a18;p=openldap diff --git a/servers/slapd/back-bdb/idl.c b/servers/slapd/back-bdb/idl.c index d793462291..5d7f321857 100644 --- a/servers/slapd/back-bdb/idl.c +++ b/servers/slapd/back-bdb/idl.c @@ -44,7 +44,7 @@ } \ } while ( 0 ) -static int +int bdb_idl_entry_cmp( const void *v_idl1, const void *v_idl2 ) { const bdb_idl_cache_entry_t *idl1 = v_idl1, *idl2 = v_idl2; @@ -304,28 +304,35 @@ bdb_idl_fetch_key( bdb_idl_cache_entry_t idl_tmp; #endif - /* buf must be large enough to grab the entire IDL in one - * get(), otherwise BDB 4 will leak resources on subsequent - * get's. We can safely call get() twice - once for the data, - * and once to get the DB_NOTFOUND result meaning there's - * no more data. See ITS#2040 for details. This bug is fixed - * in BDB 4.1 so a smaller buffer will work if stack space is - * too limited. + /* If using BerkeleyDB 4.0, the buf must be large enough to + * grab the entire IDL in one get(), otherwise BDB will leak + * resources on subsequent get's. We can safely call get() + * twice - once for the data, and once to get the DB_NOTFOUND + * result meaning there's no more data. See ITS#2040 for details. + * This bug is fixed in BDB 4.1 so a smaller buffer will work if + * stack space is too limited. + * + * configure now requires Berkeley DB 4.1. */ - ID buf[BDB_IDL_DB_SIZE*5]; +#if (DB_VERSION_MAJOR == 4) && (DB_VERSION_MINOR == 0) +# define BDB_ENOUGH 5 +#else +# define BDB_ENOUGH 1 +#endif + ID buf[BDB_IDL_DB_SIZE*BDB_ENOUGH]; + + char keybuf[16]; - { - char buf[16]; #ifdef NEW_LOGGING - LDAP_LOG( INDEX, ARGS, - "bdb_idl_fetch_key: %s\n", - bdb_show_key( key, buf ), 0, 0 ); + LDAP_LOG( INDEX, ARGS, + "bdb_idl_fetch_key: %s\n", + bdb_show_key( key, keybuf ), 0, 0 ); #else - Debug( LDAP_DEBUG_ARGS, - "bdb_idl_fetch_key: %s\n", - bdb_show_key( key, buf ), 0, 0 ); + Debug( LDAP_DEBUG_ARGS, + "bdb_idl_fetch_key: %s\n", + bdb_show_key( key, keybuf ), 0, 0 ); #endif - } + assert( ids != NULL ); #ifdef SLAP_IDL_CACHE @@ -353,8 +360,7 @@ bdb_idl_fetch_key( data.ulen = sizeof(buf); data.flags = DB_DBT_USERMEM; - if ( tid ) - flags |= DB_RMW; + if ( tid ) flags |= DB_RMW; rc = db->cursor( db, tid, &cursor, bdb->bi_db_opflags ); if( rc != 0 ) { @@ -368,6 +374,7 @@ bdb_idl_fetch_key( #endif return rc; } + rc = cursor->c_get( cursor, key, &data, flags | DB_SET ); if (rc == 0) { i = ids; @@ -406,6 +413,7 @@ bdb_idl_fetch_key( } data.size = BDB_IDL_SIZEOF(ids); } + rc2 = cursor->c_close( cursor ); if (rc2) { #ifdef NEW_LOGGING @@ -418,6 +426,7 @@ bdb_idl_fetch_key( #endif return rc2; } + if( rc == DB_NOTFOUND ) { return rc; @@ -463,33 +472,45 @@ bdb_idl_fetch_key( #ifdef SLAP_IDL_CACHE if ( bdb->bi_idl_cache_max_size ) { bdb_idl_cache_entry_t *ee; - ee = (bdb_idl_cache_entry_t *) malloc( sizeof( bdb_idl_cache_entry_t ) ); + ee = (bdb_idl_cache_entry_t *) ch_malloc( + sizeof( bdb_idl_cache_entry_t ) ); ee->db = db; - ee->idl = (ID*) malloc ( BDB_IDL_SIZEOF ( ids ) ); + ee->idl = (ID*) ch_malloc( BDB_IDL_SIZEOF ( ids ) ); ee->idl_lru_prev = NULL; ee->idl_lru_next = NULL; BDB_IDL_CPY( ee->idl, ids ); ber_dupbv( &ee->kstr, &idl_tmp.kstr ); ldap_pvt_thread_mutex_lock( &bdb->bi_idl_tree_mutex ); if ( avl_insert( &bdb->bi_idl_tree, (caddr_t) ee, - bdb_idl_entry_cmp, avl_dup_error )) { - free( ee->kstr.bv_val ); - free( ee->idl ); - free( ee ); + bdb_idl_entry_cmp, avl_dup_error )) + { + ch_free( ee->kstr.bv_val ); + ch_free( ee->idl ); + ch_free( ee ); } else { IDL_LRU_ADD( bdb, ee ); if ( ++bdb->bi_idl_cache_size > bdb->bi_idl_cache_max_size ) { int i = 0; while ( bdb->bi_idl_lru_tail != NULL && i < 10 ) { ee = bdb->bi_idl_lru_tail; - avl_delete( &bdb->bi_idl_tree, (caddr_t) ee, - bdb_idl_entry_cmp ); + if ( avl_delete( &bdb->bi_idl_tree, (caddr_t) ee, + bdb_idl_entry_cmp ) == NULL ) { +#ifdef NEW_LOGGING + LDAP_LOG( INDEX, ERR, + "bdb_idl_fetch_key: AVL delete failed\n", + 0, 0, 0 ); +#else + Debug( LDAP_DEBUG_ANY, "=> bdb_idl_fetch_key: " + "AVL delete failed\n", + 0, 0, 0 ); +#endif + } IDL_LRU_DELETE( bdb, ee ); i++; --bdb->bi_idl_cache_size; - free( ee->kstr.bv_val ); - free( ee->idl ); - free( ee ); + ch_free( ee->kstr.bv_val ); + ch_free( ee->idl ); + ch_free( ee ); } } } @@ -540,8 +561,18 @@ bdb_idl_insert_key( matched_idl_entry = avl_find( bdb->bi_idl_tree, &idl_tmp, bdb_idl_entry_cmp ); if ( matched_idl_entry != NULL ) { - avl_delete( &bdb->bi_idl_tree, (caddr_t) matched_idl_entry, - bdb_idl_entry_cmp ); + if ( avl_delete( &bdb->bi_idl_tree, (caddr_t) matched_idl_entry, + bdb_idl_entry_cmp ) == NULL ) { +#ifdef NEW_LOGGING + LDAP_LOG( INDEX, ERR, + "bdb_idl_fetch_key: AVL delete failed\n", + 0, 0, 0 ); +#else + Debug( LDAP_DEBUG_ANY, "=> bdb_idl_fetch_key: " + "AVL delete failed\n", + 0, 0, 0 ); +#endif + } --bdb->bi_idl_cache_size; IDL_LRU_DELETE( bdb, matched_idl_entry ); free( matched_idl_entry->kstr.bv_val ); @@ -752,8 +783,18 @@ bdb_idl_delete_key( matched_idl_entry = avl_find( bdb->bi_idl_tree, &idl_tmp, bdb_idl_entry_cmp ); if ( matched_idl_entry != NULL ) { - avl_delete( &bdb->bi_idl_tree, (caddr_t) matched_idl_entry, - bdb_idl_entry_cmp ); + if ( avl_delete( &bdb->bi_idl_tree, (caddr_t) matched_idl_entry, + bdb_idl_entry_cmp ) == NULL ) { +#ifdef NEW_LOGGING + LDAP_LOG( INDEX, ERR, + "bdb_idl_fetch_key: AVL delete failed\n", + 0, 0, 0 ); +#else + Debug( LDAP_DEBUG_ANY, "=> bdb_idl_fetch_key: " + "AVL delete failed\n", + 0, 0, 0 ); +#endif + } --bdb->bi_idl_cache_size; IDL_LRU_DELETE( bdb, matched_idl_entry ); free( matched_idl_entry->kstr.bv_val ); @@ -809,20 +850,17 @@ bdb_idl_delete_key( /* It's a range, see if we need to rewrite * the boundaries */ - hi = 0; data.data = &lo; rc = cursor->c_get( cursor, key, &data, DB_NEXT_DUP ); if ( rc != 0 ) { err = "c_get lo"; goto fail; } - if ( id > lo ) { - data.data = &hi; - rc = cursor->c_get( cursor, key, &data, DB_NEXT_DUP ); - if ( rc != 0 ) { - err = "c_get hi"; - goto fail; - } + data.data = &hi; + rc = cursor->c_get( cursor, key, &data, DB_NEXT_DUP ); + if ( rc != 0 ) { + err = "c_get hi"; + goto fail; } if ( id == lo || id == hi ) { if ( id == lo ) { @@ -840,6 +878,12 @@ bdb_idl_delete_key( goto fail; } } else { + if ( id == lo ) { + /* reposition on lo slot */ + data.data = &lo; + cursor->c_get( cursor, key, &data, DB_PREV ); + lo = id; + } rc = cursor->c_del( cursor, 0 ); if ( rc != 0 ) { err = "c_del";