mirror of
https://git.openldap.org/openldap/openldap.git
synced 2024-12-21 03:10:25 +08:00
Eliminated nextid database. id2entry database is now maintained in numerical
order, so the lastid is always the same as the last entry's ID. This is an incompatible db file change.
This commit is contained in:
parent
0a25cddcf3
commit
b45133c958
@ -40,10 +40,9 @@ LDAP_BEGIN_DECL
|
||||
#endif
|
||||
|
||||
#define BDB_SUFFIX ".bdb"
|
||||
#define BDB_NEXTID 0
|
||||
#define BDB_ID2ENTRY 1
|
||||
#define BDB_DN2ID 2
|
||||
#define BDB_NDB 3
|
||||
#define BDB_ID2ENTRY 0
|
||||
#define BDB_DN2ID 1
|
||||
#define BDB_NDB 2
|
||||
|
||||
#define BDB_INDICES 128
|
||||
|
||||
@ -80,9 +79,9 @@ struct bdb_info {
|
||||
#endif
|
||||
|
||||
ID bi_lastid;
|
||||
ldap_pvt_thread_mutex_t bi_lastid_mutex;
|
||||
};
|
||||
|
||||
#define bi_nextid bi_databases[BDB_NEXTID]
|
||||
#define bi_id2entry bi_databases[BDB_ID2ENTRY]
|
||||
#define bi_dn2id bi_databases[BDB_DN2ID]
|
||||
|
||||
|
@ -19,7 +19,6 @@ static struct bdbi_database {
|
||||
int type;
|
||||
int flags;
|
||||
} bdbi_databases[] = {
|
||||
{ "nextid" BDB_SUFFIX, "nextid", DB_BTREE, 0 },
|
||||
{ "id2entry" BDB_SUFFIX, "id2entry", DB_BTREE, 0 },
|
||||
{ "dn2id" BDB_SUFFIX, "dn2id", DB_BTREE, 0 },
|
||||
{ NULL, NULL, 0, 0 }
|
||||
@ -73,6 +72,7 @@ bdb_db_init( BackendDB *be )
|
||||
#endif
|
||||
|
||||
ldap_pvt_thread_mutex_init( &bdb->bi_database_mutex );
|
||||
ldap_pvt_thread_mutex_init( &bdb->bi_lastid_mutex );
|
||||
|
||||
be->be_private = bdb;
|
||||
return 0;
|
||||
@ -99,6 +99,19 @@ static void *lock_detect_task( void *arg )
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
bdb_bt_compare(
|
||||
DB *db,
|
||||
DBT *usrkey,
|
||||
DBT *curkey
|
||||
)
|
||||
{
|
||||
ID usr, cur;
|
||||
memcpy(&usr, usrkey->data, sizeof(ID));
|
||||
memcpy(&cur, curkey->data, sizeof(ID));
|
||||
return usr - cur;
|
||||
}
|
||||
|
||||
static int
|
||||
bdb_db_open( BackendDB *be )
|
||||
{
|
||||
@ -216,6 +229,10 @@ bdb_db_open( BackendDB *be )
|
||||
return rc;
|
||||
}
|
||||
|
||||
if( i == BDB_ID2ENTRY ) {
|
||||
rc = db->bdi_db->set_bt_compare( db->bdi_db,
|
||||
bdb_bt_compare );
|
||||
}
|
||||
rc = db->bdi_db->open( db->bdi_db,
|
||||
bdbi_databases[i].file,
|
||||
bdbi_databases[i].name,
|
||||
|
@ -15,160 +15,53 @@
|
||||
int bdb_next_id( BackendDB *be, DB_TXN *tid, ID *out )
|
||||
{
|
||||
struct bdb_info *bdb = (struct bdb_info *) be->be_private;
|
||||
int rc;
|
||||
ID kid = NOID;
|
||||
ID id;
|
||||
DBT key, data;
|
||||
DB_TXN *ltid = NULL;
|
||||
|
||||
DBTzero( &key );
|
||||
key.data = (char *) &kid;
|
||||
key.size = sizeof( kid );
|
||||
ldap_pvt_thread_mutex_lock( &bdb->bi_lastid_mutex );
|
||||
*out = ++bdb->bi_lastid;
|
||||
ldap_pvt_thread_mutex_unlock( &bdb->bi_lastid_mutex );
|
||||
|
||||
DBTzero( &data );
|
||||
data.data = (char *) &id;
|
||||
data.ulen = sizeof( id );
|
||||
data.flags = DB_DBT_USERMEM;
|
||||
|
||||
if( 0 ) {
|
||||
retry: if( tid != NULL ) {
|
||||
/* nested transaction, abort and return */
|
||||
(void) txn_abort( ltid );
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"=> bdb_next_id: aborted!\n",
|
||||
0, 0, 0 );
|
||||
return rc;
|
||||
}
|
||||
rc = txn_abort( ltid );
|
||||
if( rc != 0 ) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"=> bdb_next_id: txn_abort failed: %s (%d)\n",
|
||||
db_strerror(rc), rc, 0 );
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
if( bdb->bi_txn ) {
|
||||
rc = txn_begin( bdb->bi_dbenv, tid, <id, 0 );
|
||||
if( rc != 0 ) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"=> bdb_next_id: txn_begin failed: %s (%d)\n",
|
||||
db_strerror(rc), rc, 0 );
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
/* get existing value for read/modify/write */
|
||||
rc = bdb->bi_nextid->bdi_db->get( bdb->bi_nextid->bdi_db,
|
||||
ltid, &key, &data, DB_RMW );
|
||||
|
||||
switch(rc) {
|
||||
case DB_LOCK_DEADLOCK:
|
||||
case DB_LOCK_NOTGRANTED:
|
||||
goto retry;
|
||||
|
||||
case DB_NOTFOUND:
|
||||
id = 0;
|
||||
break;
|
||||
|
||||
case 0:
|
||||
if ( data.size != sizeof( id ) ) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"=> bdb_next_id: get size mismatch: expected %ld, got %ld\n",
|
||||
(long) sizeof( id ), (long) data.size, 0 );
|
||||
rc = -1;
|
||||
goto done;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"=> bdb_next_id: get failed: %s (%d)\n",
|
||||
db_strerror(rc), rc, 0 );
|
||||
goto done;
|
||||
}
|
||||
|
||||
if( bdb->bi_lastid > id ) id = bdb->bi_lastid;
|
||||
|
||||
id++;
|
||||
data.size = sizeof( id );
|
||||
|
||||
/* put new value */
|
||||
rc = bdb->bi_nextid->bdi_db->put( bdb->bi_nextid->bdi_db,
|
||||
ltid, &key, &data, 0 );
|
||||
|
||||
switch(rc) {
|
||||
case DB_LOCK_DEADLOCK:
|
||||
case DB_LOCK_NOTGRANTED:
|
||||
goto retry;
|
||||
|
||||
case 0:
|
||||
*out = id;
|
||||
|
||||
bdb->bi_lastid = id;
|
||||
|
||||
if (bdb->bi_txn) {
|
||||
rc = txn_commit( ltid, 0 );
|
||||
ltid = NULL;
|
||||
}
|
||||
|
||||
if( rc != 0 ) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"=> bdb_next_id: commit failed: %s (%d)\n",
|
||||
db_strerror(rc), rc, 0 );
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"=> bdb_next_id: put failed: %s (%d)\n",
|
||||
db_strerror(rc), rc, 0 );
|
||||
done: (void) txn_abort( ltid );
|
||||
}
|
||||
|
||||
return rc;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bdb_last_id( BackendDB *be, DB_TXN *tid )
|
||||
{
|
||||
struct bdb_info *bdb = (struct bdb_info *) be->be_private;
|
||||
int rc;
|
||||
ID kid = NOID;
|
||||
ID id;
|
||||
ID id = 0;
|
||||
DBT key, data;
|
||||
DBC *cursor;
|
||||
|
||||
DBTzero( &key );
|
||||
key.data = (char *) &kid;
|
||||
key.size = sizeof( kid );
|
||||
key.flags = DB_DBT_USERMEM;
|
||||
key.data = (char *) &id;
|
||||
key.ulen = sizeof( id );
|
||||
|
||||
DBTzero( &data );
|
||||
data.data = (char *) &id;
|
||||
data.ulen = sizeof( id );
|
||||
data.flags = DB_DBT_USERMEM;
|
||||
data.flags = DB_DBT_USERMEM | DB_DBT_PARTIAL;
|
||||
|
||||
/* get existing value for read/modify/write */
|
||||
rc = bdb->bi_nextid->bdi_db->get( bdb->bi_nextid->bdi_db,
|
||||
tid, &key, &data, 0 );
|
||||
/* Get a read cursor */
|
||||
rc = bdb->bi_id2entry->bdi_db->cursor( bdb->bi_id2entry->bdi_db,
|
||||
tid, &cursor, 0 );
|
||||
|
||||
while (rc == 0) {
|
||||
rc = cursor->c_get(cursor, &key, &data, DB_LAST);
|
||||
cursor->c_close(cursor);
|
||||
if (rc != 0)
|
||||
break;
|
||||
break;
|
||||
}
|
||||
|
||||
switch(rc) {
|
||||
case DB_NOTFOUND:
|
||||
id = 0;
|
||||
rc = 0;
|
||||
break;
|
||||
|
||||
/* FALLTHROUGH */
|
||||
case 0:
|
||||
if ( data.size != sizeof( id ) ) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"=> bdb_last_id: get size mismatch: expected %ld, got %ld\n",
|
||||
(long) sizeof( id ), (long) data.size, 0 );
|
||||
rc = -1;
|
||||
goto done;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"=> bdb_next_id: get failed: %s (%d)\n",
|
||||
"=> bdb_last_id: get failed: %s (%d)\n",
|
||||
db_strerror(rc), rc, 0 );
|
||||
goto done;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user