From: Kurt Zeilenga Date: Fri, 22 Sep 2000 06:46:32 +0000 (+0000) Subject: Add bdb_add() and supporting routines X-Git-Tag: LDBM_PRE_GIANT_RWLOCK~1922 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=aaab54e14270a6ba1d6d16f9b0b9bcf52a7c8cba;p=openldap Add bdb_add() and supporting routines --- diff --git a/servers/slapd/back-bdb/add.c b/servers/slapd/back-bdb/add.c new file mode 100644 index 0000000000..f59e5aad60 --- /dev/null +++ b/servers/slapd/back-bdb/add.c @@ -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 +#include + +#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, <id, 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; +} diff --git a/servers/slapd/back-bdb/back-bdb.h b/servers/slapd/back-bdb/back-bdb.h index 7efbfcb4b7..06361d7530 100644 --- a/servers/slapd/back-bdb/back-bdb.h +++ b/servers/slapd/back-bdb/back-bdb.h @@ -39,10 +39,10 @@ LDAP_BEGIN_DECL #define BDB_LG_SUBDIR LDAP_DIRSEP "log" #define BDB_DATA_SUBDIR LDAP_DIRSEP "data" -#define BDB_NEXTID 0 -#define BDB_ENTRIES 1 -#define BDB_DN2ID 2 -#define BDB_INDICES 3 +#define BDB_NEXTID 0 +#define BDB_DN2ID 1 +#define BDB_ID2ENTRY 2 +#define BDB_INDICES 3 struct bdb_db_info { DB *bdi_db; @@ -61,7 +61,7 @@ struct bdb_info { struct bdb_db_info **bi_databases; }; #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] LDAP_END_DECL diff --git a/servers/slapd/back-bdb/backbdb.dsp b/servers/slapd/back-bdb/backbdb.dsp index cb8048b048..da06c6bec6 100644 --- a/servers/slapd/back-bdb/backbdb.dsp +++ b/servers/slapd/back-bdb/backbdb.dsp @@ -147,6 +147,10 @@ SOURCE=.\external.h # End Source File # Begin Source File +SOURCE=.\id2entry.c +# End Source File +# Begin Source File + SOURCE=.\idl.c # End Source File # Begin Source File diff --git a/servers/slapd/back-bdb/dn2id.c b/servers/slapd/back-bdb/dn2id.c index b008849573..1e0f0b6d7b 100644 --- a/servers/slapd/back-bdb/dn2id.c +++ b/servers/slapd/back-bdb/dn2id.c @@ -15,7 +15,7 @@ #include "back-bdb.h" int -bdb_index_dn_add( +bdb_dn2id_add( Backend *be, DB_TXN *txn, const char *dn, diff --git a/servers/slapd/back-bdb/error.c b/servers/slapd/back-bdb/error.c index 56a6e0572b..aced7cf0da 100644 --- a/servers/slapd/back-bdb/error.c +++ b/servers/slapd/back-bdb/error.c @@ -10,7 +10,6 @@ #include #include -#include #include "slap.h" #include "back-bdb.h" diff --git a/servers/slapd/back-bdb/id2entry.c b/servers/slapd/back-bdb/id2entry.c new file mode 100644 index 0000000000..f613b910a3 --- /dev/null +++ b/servers/slapd/back-bdb/id2entry.c @@ -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 +#include + +#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; +} diff --git a/servers/slapd/back-bdb/idl.c b/servers/slapd/back-bdb/idl.c index e1a36ed165..c3f2148ce5 100644 --- a/servers/slapd/back-bdb/idl.c +++ b/servers/slapd/back-bdb/idl.c @@ -8,9 +8,7 @@ #include "portable.h" #include - #include -#include #include "back-bdb.h" diff --git a/servers/slapd/back-bdb/init.c b/servers/slapd/back-bdb/init.c index 74d56e6801..c7f2d9d4e2 100644 --- a/servers/slapd/back-bdb/init.c +++ b/servers/slapd/back-bdb/init.c @@ -8,9 +8,7 @@ #include "portable.h" #include - #include -#include #include "back-bdb.h" @@ -21,8 +19,8 @@ static struct bdbi_database { int flags; } bdbi_databases[BDB_INDICES] = { { "nextid", "nextid", DB_BTREE, 0 }, + { "dn2entry", "dn2entry", DB_BTREE, 0 }, { "id2entry", "id2entry", DB_BTREE, 0 }, - { "dn2entry", "dn2entry", DB_BTREE, 0 } }; static int @@ -283,11 +281,11 @@ bdb_initialize( 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_attribute = bi_back_attribute; bi->bi_chk_referrals = bi_back_referrals; #endif + bi->bi_entry_release_rw = 0; /* * hooks for slap tools diff --git a/servers/slapd/back-bdb/nextid.c b/servers/slapd/back-bdb/nextid.c index acf15046c7..68f87b3fd9 100644 --- a/servers/slapd/back-bdb/nextid.c +++ b/servers/slapd/back-bdb/nextid.c @@ -8,9 +8,7 @@ #include "portable.h" #include - #include -#include #include "back-bdb.h" @@ -38,7 +36,7 @@ int bdb_next_id( BackendDB *be, DB_TXN *tid, ID *out ) data.flags = DB_DBT_USERMEM; /* 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 ); if( rc == DB_NOTFOUND ) { @@ -57,7 +55,7 @@ int bdb_next_id( BackendDB *be, DB_TXN *tid, ID *out ) id++; /* 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 ); *out = id; diff --git a/servers/slapd/back-bdb/proto-bdb.h b/servers/slapd/back-bdb/proto-bdb.h index e87da339fc..1992fe6ed0 100644 --- a/servers/slapd/back-bdb/proto-bdb.h +++ b/servers/slapd/back-bdb/proto-bdb.h @@ -9,7 +9,6 @@ LDAP_BEGIN_DECL - /* * alias.c */ @@ -29,7 +28,7 @@ Entry *bdb_deref_internal_r LDAP_P(( /* * dn2id.c */ -int bdb_index_dn_add( +int bdb_dn2id_add( BackendDB *be, DB_TXN *tid, 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_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 */ void bdb_errcall( const char *pfx, char * msg ); +/* + * id2entry + */ +int bdb_id2entry_add( + Backend *be, + DB_TXN *tid, + Entry *e ); + /* * idl.c */ diff --git a/servers/slapd/back-bdb/tools.c b/servers/slapd/back-bdb/tools.c index 686fd9ff6e..11b96f3b9b 100644 --- a/servers/slapd/back-bdb/tools.c +++ b/servers/slapd/back-bdb/tools.c @@ -8,9 +8,7 @@ #include "portable.h" #include - #include -#include #include "back-bdb.h" @@ -23,8 +21,8 @@ int bdb_tool_entry_open( int rc; struct bdb_info *bdb = (struct bdb_info *) be->be_private; - rc = bdb->bi_entries->bdi_db->cursor( - bdb->bi_entries->bdi_db, NULL, &cursor, 0 ); + rc = bdb->bi_id2entry->bdi_db->cursor( + bdb->bi_id2entry->bdi_db, NULL, &cursor, 0 ); if( rc != 0 ) { return NOID; } @@ -109,29 +107,14 @@ ID bdb_tool_entry_put( int rc; struct bdb_info *bdb = (struct bdb_info *) be->be_private; DB_TXN *tid; - DBT key, data; - struct berval *bv; 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", e->e_id, e->e_dn, 0 ); rc = txn_begin( bdb->bi_dbenv, NULL, &tid, 0 ); if( rc != 0 ) { - ber_bvfree( bv ); return NOID; } @@ -140,15 +123,14 @@ ID bdb_tool_entry_put( goto done; } - /* store it -- don't override */ - rc = bdb->bi_entries->bdi_db->put( bdb->bi_entries->bdi_db, - tid, &key, &data, DB_NOOVERWRITE ); + /* add dn2id indices */ + rc = bdb_dn2id_add( be, tid, e->e_ndn, e->e_id ); if( rc != 0 ) { goto done; } - /* add dn indices */ - rc = bdb_index_dn_add( be, tid, e->e_ndn, e->e_id ); + /* id2entry index */ + rc = bdb_id2entry_add( be, tid, e ); if( rc != 0 ) { goto done; } @@ -161,8 +143,6 @@ ID bdb_tool_entry_put( #endif done: - ber_bvfree( bv ); - if( rc == 0 ) { rc = txn_commit( tid, 0 ); if( rc != 0 ) {