Add bdb_add() and supporting routines

This commit is contained in:
Kurt Zeilenga 2000-09-22 06:46:32 +00:00
parent 2b82d4f486
commit aaab54e142
11 changed files with 313 additions and 45 deletions

View File

@ -0,0 +1,237 @@
/* add.c - ldap BerkeleyDB back-end add routine */
/* $OpenLDAP$ */
/*
* Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved.
* COPYING RESTRICTIONS APPLY, see COPYRIGHT file
*/
#include "portable.h"
#include <stdio.h>
#include <ac/string.h>
#include "back-bdb.h"
int
bdb_add(
Backend *be,
Connection *conn,
Operation *op,
Entry *e )
{
struct bdb_info *bdb = (struct bdb_info *) be->be_private;
char *pdn = NULL;
Entry *p = NULL;
int rootlock = 0;
int rc;
const char *text = NULL;
AttributeDescription *children = slap_schema.si_ad_children;
DB_TXN *ltid = NULL;
Debug(LDAP_DEBUG_ARGS, "==> bdb_add: %s\n", e->e_dn, 0, 0);
/* check entry's schema */
rc = entry_schema_check( e, NULL, &text );
if ( rc != LDAP_SUCCESS ) {
Debug( LDAP_DEBUG_TRACE,
"bdb_add: entry failed schema check: %s (%d)\n",
text, rc, 0 );
goto return_results;
}
/*
* acquire an ID outside of the operation transaction
* to avoid serializing adds.
*/
rc = bdb_next_id( be, NULL, &e->e_id );
if( rc != 0 ) {
Debug( LDAP_DEBUG_TRACE,
"bdb_add: next_id failed (%d)\n",
rc, 0, 0 );
rc = LDAP_OTHER;
text = "internal error";
goto return_results;
}
/* begin transaction */
rc = txn_begin( bdb->bi_dbenv, NULL, &ltid, 0 );
if( rc != 0 ) {
Debug( LDAP_DEBUG_TRACE,
"bdb_add: txn_begin failed: %s (%d)\n",
db_strerror(rc), rc, 0 );
rc = LDAP_OTHER;
text = "internal error";
goto return_results;
}
/*
* Get the parent dn and see if the corresponding entry exists.
* If the parent does not exist, only allow the "root" user to
* add the entry.
*/
pdn = dn_parent( be, e->e_ndn );
if( pdn != NULL && *pdn != '\0' ) {
Entry *matched = NULL;
/* get parent with reader lock */
p = dn2entry_r( be, ltid, pdn, &matched );
if ( p == NULL ) {
char *matched_dn;
struct berval **refs;
ch_free( pdn );
if ( matched != NULL ) {
matched_dn = ch_strdup( matched->e_dn );
refs = is_entry_referral( matched )
? get_entry_referrals( be, conn, op, matched )
: NULL;
bdb_entry_return( be, matched );
} else {
matched_dn = NULL;
refs = default_referral;
}
Debug( LDAP_DEBUG_TRACE, "bdb_add: parent does not exist\n",
0, 0, 0 );
send_ldap_result( conn, op, rc = LDAP_REFERRAL,
matched_dn, NULL, refs, NULL );
if( matched != NULL ) {
ber_bvecfree( refs );
ch_free( matched_dn );
}
goto done;
}
ch_free(pdn);
if ( ! access_allowed( be, conn, op, p,
children, NULL, ACL_WRITE ) )
{
Debug( LDAP_DEBUG_TRACE, "bdb_add: no write access to parent\n",
0, 0, 0 );
rc = LDAP_INSUFFICIENT_ACCESS;
text = "no write access to parent", NULL, NULL;
goto return_results;;
}
if ( is_entry_alias( p ) ) {
/* parent is an alias, don't allow add */
Debug( LDAP_DEBUG_TRACE, "bdb_add: parent is alias\n",
0, 0, 0 );
rc = LDAP_ALIAS_PROBLEM;
text = "parent is an alias";
goto return_results;;
}
if ( is_entry_referral( p ) ) {
/* parent is a referral, don't allow add */
char *matched_dn = ch_strdup( p->e_dn );
struct berval **refs = is_entry_referral( p )
? get_entry_referrals( be, conn, op, p )
: NULL;
Debug( LDAP_DEBUG_TRACE, "bdb_add: parent is referral\n",
0, 0, 0 );
send_ldap_result( conn, op, rc = LDAP_REFERRAL,
matched_dn, NULL, refs, NULL );
ber_bvecfree( refs );
free( matched_dn );
goto done;
}
} else {
if( pdn != NULL ) {
free(pdn);
}
/*
* no parent!
* must be adding entry to at suffix
* or with parent ""
*/
if ( !be_isroot( be, op->o_ndn )) {
Debug( LDAP_DEBUG_TRACE, "bdb_add: %s denied\n",
pdn == NULL ? "suffix" : "entry at root",
0, 0 );
rc = LDAP_INSUFFICIENT_ACCESS;
goto return_results;
}
}
/* dn2id index */
rc = bdb_dn2id_add( be, ltid, e->e_ndn, e->e_id );
if ( rc != 0 ) {
Debug( LDAP_DEBUG_TRACE, "bdb_add: dn2id_add failed: %s (%d)\n",
db_strerror(rc), rc, 0 );
if( rc == DB_KEYEXIST ) {
rc = LDAP_ALREADY_EXISTS;
} else {
rc = LDAP_OTHER;
}
goto return_results;
}
/* id2entry index */
rc = bdb_id2entry_add( be, ltid, e );
if ( rc != 0 ) {
Debug( LDAP_DEBUG_TRACE, "bdb_add: id2entry_add failed\n",
0, 0, 0 );
rc = LDAP_OTHER;
text = "entry store failed";
goto return_results;
}
#if 0
/* attribute indexes */
if ( index_entry_add( be, e, e->e_attrs ) != LDAP_SUCCESS ) {
Debug( LDAP_DEBUG_TRACE, "bdb_add: index_entry_add failed\n",
0, 0, 0 );
rc = LDAP_OTHER;
text = "index generation failed";
goto return_results;
}
#endif
rc = txn_commit( ltid, 0 );
ltid = NULL;
if( rc == 0 ) {
Debug( LDAP_DEBUG_TRACE,
"bdb_add: txn_commit failed: %s (%d)\n",
db_strerror(rc), rc, 0 );
rc = LDAP_OTHER;
text = "commit failed";
} else {
Debug( LDAP_DEBUG_TRACE,
"bdb_add: added id=%08x dn=\"%s\"\n",
e->e_id, e->e_dn, 0 );
rc = LDAP_SUCCESS;
text = NULL;
}
return_results:
send_ldap_result( conn, op, rc,
NULL, text, NULL, NULL );
done:
if (p != NULL) {
/* free parent and writer lock */
bdb_entry_return( be, p );
}
if( ltid != NULL ) {
txn_abort( ltid );
}
return rc;
}

View File

@ -39,10 +39,10 @@ LDAP_BEGIN_DECL
#define BDB_LG_SUBDIR LDAP_DIRSEP "log" #define BDB_LG_SUBDIR LDAP_DIRSEP "log"
#define BDB_DATA_SUBDIR LDAP_DIRSEP "data" #define BDB_DATA_SUBDIR LDAP_DIRSEP "data"
#define BDB_NEXTID 0 #define BDB_NEXTID 0
#define BDB_ENTRIES 1 #define BDB_DN2ID 1
#define BDB_DN2ID 2 #define BDB_ID2ENTRY 2
#define BDB_INDICES 3 #define BDB_INDICES 3
struct bdb_db_info { struct bdb_db_info {
DB *bdi_db; DB *bdi_db;
@ -61,7 +61,7 @@ struct bdb_info {
struct bdb_db_info **bi_databases; struct bdb_db_info **bi_databases;
}; };
#define bi_nextid bi_databases[BDB_NEXTID] #define bi_nextid bi_databases[BDB_NEXTID]
#define bi_entries bi_databases[BDB_ENTRIES] #define bi_id2entry bi_databases[BDB_ID2ENTRY]
#define bi_dn2id bi_databases[BDB_DN2ID] #define bi_dn2id bi_databases[BDB_DN2ID]
LDAP_END_DECL LDAP_END_DECL

View File

@ -147,6 +147,10 @@ SOURCE=.\external.h
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=.\id2entry.c
# End Source File
# Begin Source File
SOURCE=.\idl.c SOURCE=.\idl.c
# End Source File # End Source File
# Begin Source File # Begin Source File

View File

@ -15,7 +15,7 @@
#include "back-bdb.h" #include "back-bdb.h"
int int
bdb_index_dn_add( bdb_dn2id_add(
Backend *be, Backend *be,
DB_TXN *txn, DB_TXN *txn,
const char *dn, const char *dn,

View File

@ -10,7 +10,6 @@
#include <stdio.h> #include <stdio.h>
#include <ac/string.h> #include <ac/string.h>
#include <ac/socket.h>
#include "slap.h" #include "slap.h"
#include "back-bdb.h" #include "back-bdb.h"

View File

@ -0,0 +1,42 @@
/* id2entry.c - routines to deal with the id2entry database */
/* $OpenLDAP$ */
/*
* Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved.
* COPYING RESTRICTIONS APPLY, see COPYRIGHT file
*/
#include "portable.h"
#include <stdio.h>
#include <ac/string.h>
#include "back-bdb.h"
int bdb_id2entry_add(
Backend *be,
DB_TXN *tid,
Entry *e )
{
struct bdb_info *bdb = (struct bdb_info *) be->be_private;
DBT key, data;
struct berval *bv;
int rc;
DBTzero( &key );
key.data = (char *) &e->e_id;
key.size = sizeof(ID);
rc = entry_encode( e, &bv );
if( rc != LDAP_SUCCESS ) {
return -1;
}
DBTzero( &data );
bv2DBT( bv, &data );
rc = bdb->bi_id2entry->bdi_db->put( bdb->bi_id2entry->bdi_db,
tid, &key, &data, DB_NOOVERWRITE );
ber_bvfree( bv );
return rc;
}

View File

@ -8,9 +8,7 @@
#include "portable.h" #include "portable.h"
#include <stdio.h> #include <stdio.h>
#include <ac/string.h> #include <ac/string.h>
#include <ac/socket.h>
#include "back-bdb.h" #include "back-bdb.h"

View File

@ -8,9 +8,7 @@
#include "portable.h" #include "portable.h"
#include <stdio.h> #include <stdio.h>
#include <ac/string.h> #include <ac/string.h>
#include <ac/socket.h>
#include "back-bdb.h" #include "back-bdb.h"
@ -21,8 +19,8 @@ static struct bdbi_database {
int flags; int flags;
} bdbi_databases[BDB_INDICES] = { } bdbi_databases[BDB_INDICES] = {
{ "nextid", "nextid", DB_BTREE, 0 }, { "nextid", "nextid", DB_BTREE, 0 },
{ "dn2entry", "dn2entry", DB_BTREE, 0 },
{ "id2entry", "id2entry", DB_BTREE, 0 }, { "id2entry", "id2entry", DB_BTREE, 0 },
{ "dn2entry", "dn2entry", DB_BTREE, 0 }
}; };
static int static int
@ -283,11 +281,11 @@ bdb_initialize(
bi->bi_extended = bi_back_extended; bi->bi_extended = bi_back_extended;
bi->bi_entry_release_rw = bi_back_entry_release_rw;
bi->bi_acl_group = bi_back_group; bi->bi_acl_group = bi_back_group;
bi->bi_acl_attribute = bi_back_attribute; bi->bi_acl_attribute = bi_back_attribute;
bi->bi_chk_referrals = bi_back_referrals; bi->bi_chk_referrals = bi_back_referrals;
#endif #endif
bi->bi_entry_release_rw = 0;
/* /*
* hooks for slap tools * hooks for slap tools

View File

@ -8,9 +8,7 @@
#include "portable.h" #include "portable.h"
#include <stdio.h> #include <stdio.h>
#include <ac/string.h> #include <ac/string.h>
#include <ac/socket.h>
#include "back-bdb.h" #include "back-bdb.h"
@ -38,7 +36,7 @@ int bdb_next_id( BackendDB *be, DB_TXN *tid, ID *out )
data.flags = DB_DBT_USERMEM; data.flags = DB_DBT_USERMEM;
/* get exiting value (with write lock) */ /* get exiting value (with write lock) */
rc = bdb->bi_entries->bdi_db->get( bdb->bi_nextid->bdi_db, rc = bdb->bi_nextid->bdi_db->get( bdb->bi_nextid->bdi_db,
ltid, &key, &data, DB_RMW ); ltid, &key, &data, DB_RMW );
if( rc == DB_NOTFOUND ) { if( rc == DB_NOTFOUND ) {
@ -57,7 +55,7 @@ int bdb_next_id( BackendDB *be, DB_TXN *tid, ID *out )
id++; id++;
/* store new value */ /* store new value */
rc = bdb->bi_entries->bdi_db->put( bdb->bi_nextid->bdi_db, rc = bdb->bi_nextid->bdi_db->put( bdb->bi_nextid->bdi_db,
ltid, &key, &data, 0 ); ltid, &key, &data, 0 );
*out = id; *out = id;

View File

@ -9,7 +9,6 @@
LDAP_BEGIN_DECL LDAP_BEGIN_DECL
/* /*
* alias.c * alias.c
*/ */
@ -29,7 +28,7 @@ Entry *bdb_deref_internal_r LDAP_P((
/* /*
* dn2id.c * dn2id.c
*/ */
int bdb_index_dn_add( int bdb_dn2id_add(
BackendDB *be, BackendDB *be,
DB_TXN *tid, DB_TXN *tid,
const char *dn, const char *dn,
@ -41,11 +40,24 @@ Entry * bdb_dn2entry_rw LDAP_P(( Backend *be, DB_TXN *tid,
#define dn2entry_r(be, tid, dn, m) bdb_dn2entry_rw((be), (tid), (dn), (m), 0) #define dn2entry_r(be, tid, dn, m) bdb_dn2entry_rw((be), (tid), (dn), (m), 0)
#define dn2entry_w(be, tid, dn, m) bdb_dn2entry_rw((be), (tid), (dn), (m), 1) #define dn2entry_w(be, tid, dn, m) bdb_dn2entry_rw((be), (tid), (dn), (m), 1)
/*
* entry.c
*/
int bdb_entry_return( BackendDB *be, Entry *e );
/* /*
* error.c * error.c
*/ */
void bdb_errcall( const char *pfx, char * msg ); void bdb_errcall( const char *pfx, char * msg );
/*
* id2entry
*/
int bdb_id2entry_add(
Backend *be,
DB_TXN *tid,
Entry *e );
/* /*
* idl.c * idl.c
*/ */

View File

@ -8,9 +8,7 @@
#include "portable.h" #include "portable.h"
#include <stdio.h> #include <stdio.h>
#include <ac/string.h> #include <ac/string.h>
#include <ac/socket.h>
#include "back-bdb.h" #include "back-bdb.h"
@ -23,8 +21,8 @@ int bdb_tool_entry_open(
int rc; int rc;
struct bdb_info *bdb = (struct bdb_info *) be->be_private; struct bdb_info *bdb = (struct bdb_info *) be->be_private;
rc = bdb->bi_entries->bdi_db->cursor( rc = bdb->bi_id2entry->bdi_db->cursor(
bdb->bi_entries->bdi_db, NULL, &cursor, 0 ); bdb->bi_id2entry->bdi_db, NULL, &cursor, 0 );
if( rc != 0 ) { if( rc != 0 ) {
return NOID; return NOID;
} }
@ -109,29 +107,14 @@ ID bdb_tool_entry_put(
int rc; int rc;
struct bdb_info *bdb = (struct bdb_info *) be->be_private; struct bdb_info *bdb = (struct bdb_info *) be->be_private;
DB_TXN *tid; DB_TXN *tid;
DBT key, data;
struct berval *bv;
assert( slapMode & SLAP_TOOL_MODE ); assert( slapMode & SLAP_TOOL_MODE );
DBTzero( &key );
key.data = (char *) &e->e_id;
key.size = sizeof(ID);
rc = entry_encode( e, &bv );
if( rc != LDAP_SUCCESS ) {
return NOID;
}
DBTzero( &data );
bv2DBT( bv, &data );
Debug( LDAP_DEBUG_TRACE, "=> bdb_tool_entry_put( %ld, \"%s\" )\n", Debug( LDAP_DEBUG_TRACE, "=> bdb_tool_entry_put( %ld, \"%s\" )\n",
e->e_id, e->e_dn, 0 ); e->e_id, e->e_dn, 0 );
rc = txn_begin( bdb->bi_dbenv, NULL, &tid, 0 ); rc = txn_begin( bdb->bi_dbenv, NULL, &tid, 0 );
if( rc != 0 ) { if( rc != 0 ) {
ber_bvfree( bv );
return NOID; return NOID;
} }
@ -140,15 +123,14 @@ ID bdb_tool_entry_put(
goto done; goto done;
} }
/* store it -- don't override */ /* add dn2id indices */
rc = bdb->bi_entries->bdi_db->put( bdb->bi_entries->bdi_db, rc = bdb_dn2id_add( be, tid, e->e_ndn, e->e_id );
tid, &key, &data, DB_NOOVERWRITE );
if( rc != 0 ) { if( rc != 0 ) {
goto done; goto done;
} }
/* add dn indices */ /* id2entry index */
rc = bdb_index_dn_add( be, tid, e->e_ndn, e->e_id ); rc = bdb_id2entry_add( be, tid, e );
if( rc != 0 ) { if( rc != 0 ) {
goto done; goto done;
} }
@ -161,8 +143,6 @@ ID bdb_tool_entry_put(
#endif #endif
done: done:
ber_bvfree( bv );
if( rc == 0 ) { if( rc == 0 ) {
rc = txn_commit( tid, 0 ); rc = txn_commit( tid, 0 );
if( rc != 0 ) { if( rc != 0 ) {