ITS#9463 cumulative fix for back-wt

- LDAP MODRDN handling
- support paged response
- add wt_extended
- add config emit
- wt_key_read() return WT_NOTFOUND if not found key.
- add ext_candidates()
- fix idlcache session name
- fix warning
- don't reuse idlcache cursor
- set correct pid when modrdn with newsuperior
- fix condition bug
- fix send_search_entry() error handling
- fix for referral handling
- fix for readonly mode
- fix sizelimit response
- support modrdn
- improve modify handling
- clear ancestor idlcache
- fix for multi-DIT
- IMPORTANT CHANGES: Compatibility is broken with previous database table, please restore database from LDIF.
- checking for scope=children
- sort dn2idl result
- fix cursor leak
- support db_open with readonly mode
- add wt_tool_entry_delete
- initialize comp variable
- support referrals
- implement wt_tool_dn2id_get() and wt_tool_entry_modify() for slapadd -w
- skip redundant scan, and more debug message
- fix OID conflict with back-passwd
- no need to close session, It may cause SEGV.
- fixed wt_dn2entry for empty DN
- support multiple database
- Construct wiredtiger's config parameter. It allow multi line wtconfig settings
- add idlcache
- fix concurrent modification to a entry with multi values
- prevent to add duplicate dn entry
- suppress error message "search_near failed: WT_NOTFOUND"
- update Debug statements
- back-wt does not support subtree rename
- fix for @ondra review
- update slapd-wt.5 and warning for mode option
- add back-wt test into test target
- add scope checking
This commit is contained in:
HAMANO Tsukasa 2021-02-10 22:56:09 +09:00 committed by Quanah Gibson-Mount
parent f19a1da188
commit 2aaaf98315
34 changed files with 2480 additions and 814 deletions

View file

@ -33,6 +33,25 @@ A separate directory must be specified for each database.
The default is
.BR LOCALSTATEDIR/openldap\-data .
.TP
.BI idlcache \ <boolean>
Use the in-memory idlcache. The default is true.
.TP
\fBindex \fR{\fI<attrlist>\fR|\fBdefault\fR} [\fBpres\fR,\fBeq\fR,\fBapprox\fR,\fBsub\fR,\fI<special>\fR]
Specify the indexes to maintain for the given attribute (or
list of attributes).
Some attributes only support a subset of indexes.
If only an \fI<attr>\fP is given, the indices specified for \fBdefault\fR
are maintained.
Note that setting a default does not imply that all attributes will be
indexed. Also, for best performance, an
.B eq
index should always be configured for the
.B objectClass
attribute.
.TP
.BI mode \ <integer>
back-wt does not support mode option. use umask instead.
.TP
\fBwtconfig \fR{\fBcreate\fR,\fBcache_size=512M\fR,\fBasync=(enabled)\fR}
Specify configuration for wiredtiger, This parameter is pass to
.BR wiredtiger_open (3).
@ -52,19 +71,6 @@ maximum heap memory to allocate for the cache.
asynchronous operations configuration options. disabled by default.
.RE
.RS
.TP
\fBindex \fR{\fI<attrlist>\fR|\fBdefault\fR} [\fBpres\fR,\fBeq\fR,\fBapprox\fR,\fBsub\fR,\fI<special>\fR]
Specify the indexes to maintain for the given attribute (or
list of attributes).
Some attributes only support a subset of indexes.
If only an \fI<attr>\fP is given, the indices specified for \fBdefault\fR
are maintained.
Note that setting a default does not imply that all attributes will be
indexed. Also, for best performance, an
.B eq
index should always be configured for the
.B objectClass
attribute.
.SH ACCESS CONTROL
The

View file

@ -14,18 +14,18 @@
## <http://www.OpenLDAP.org/license.html>.
SRCS = init.c tools.c config.c \
add.c bind.c compare.c delete.c modify.c search.c \
operational.c \
add.c bind.c compare.c delete.c modify.c modrdn.c search.c \
extended.c operational.c \
attr.c index.c key.c filterindex.c \
dn2entry.c dn2id.c id2entry.c idl.c \
nextid.c ctx.c
nextid.c ctx.c cache.c
OBJS = init.lo tools.lo config.lo \
add.lo bind.lo compare.lo delete.lo modify.lo search.lo \
operational.lo \
add.lo bind.lo compare.lo delete.lo modify.lo modrdn.lo search.lo \
extended.lo operational.lo \
attr.lo index.lo key.lo filterindex.lo \
dn2entry.lo dn2id.lo id2entry.lo idl.lo \
nextid.lo ctx.lo
nextid.lo ctx.lo cache.lo
LDAP_INCDIR= ../../../include
LDAP_LIBDIR= ../../../libraries

View file

@ -34,20 +34,17 @@ wt_add( Operation *op, SlapReply *rs )
size_t textlen = sizeof textbuf;
AttributeDescription *children = slap_schema.si_ad_children;
AttributeDescription *entry = slap_schema.si_ad_entry;
ID eid;
int num_retries = 0;
int success;
ID eid = NOID;
LDAPControl **postread_ctrl = NULL;
LDAPControl *ctrls[SLAP_MAX_RESPONSE_CONTROLS];
int num_ctrls = 0;
wt_ctx *wc;
Entry *e = NULL;
Entry *p = NULL;
ID pid;
ID pid = NOID;
int rc;
Debug( LDAP_DEBUG_ARGS, "==> " LDAP_XSTRING(wt_add) ": %s\n",
op->ora_e->e_name.bv_val );
Debug( LDAP_DEBUG_ARGS, "==> wt_add: %s\n", op->ora_e->e_name.bv_val );
ctrls[num_ctrls] = 0;
@ -57,8 +54,7 @@ wt_add( Operation *op, SlapReply *rs )
get_relax(op), 1, NULL, &rs->sr_text, textbuf, textlen );
if ( rs->sr_err != LDAP_SUCCESS ) {
Debug( LDAP_DEBUG_TRACE,
LDAP_XSTRING(wt_add)
": entry failed schema check: %s (%d)\n",
"wt_add: entry failed schema check: %s (%d)\n",
rs->sr_text, rs->sr_err );
goto return_results;
}
@ -68,8 +64,7 @@ wt_add( Operation *op, SlapReply *rs )
rs->sr_err = slap_add_opattrs( op, &rs->sr_text, textbuf, textlen, 1 );
if ( rs->sr_err != LDAP_SUCCESS ) {
Debug( LDAP_DEBUG_TRACE,
LDAP_XSTRING(wt_add)
": entry failed op attrs add: %s (%d)\n",
"wt_add: entry failed op attrs add: %s (%d)\n",
rs->sr_text, rs->sr_err );
goto return_results;
}
@ -97,9 +92,7 @@ wt_add( Operation *op, SlapReply *rs )
wc = wt_ctx_get(op, wi);
if( !wc ){
Debug( LDAP_DEBUG_ANY,
LDAP_XSTRING(wt_add)
": wt_ctx_get failed\n" );
Debug( LDAP_DEBUG_ANY, "wt_add: wt_ctx_get failed\n" );
rs->sr_err = LDAP_OTHER;
rs->sr_text = "internal error";
send_ldap_result( op, rs );
@ -117,9 +110,7 @@ wt_add( Operation *op, SlapReply *rs )
default:
/* TODO: retry handling */
Debug( LDAP_DEBUG_ANY,
LDAP_XSTRING(wt_add)
": error at wt_dn2entry() rc=%d\n",
rc );
"wt_add: error at wt_dn2entry() rc=%d\n", rc );
rs->sr_err = LDAP_OTHER;
rs->sr_text = "internal error";
goto return_results;
@ -133,9 +124,7 @@ wt_add( Operation *op, SlapReply *rs )
break;
default:
Debug( LDAP_DEBUG_ANY,
LDAP_XSTRING(wt_add)
": error at wt_dn2pentry() rc=%d\n",
rc );
"wt_add: error at wt_dn2pentry() rc=%d\n", rc );
rs->sr_err = LDAP_OTHER;
rs->sr_text = "internal error";
goto return_results;
@ -156,9 +145,7 @@ wt_add( Operation *op, SlapReply *rs )
rs->sr_ref = NULL;
}
p = NULL;
Debug( LDAP_DEBUG_TRACE,
LDAP_XSTRING(wt_add) ": parent "
"does not exist\n" );
Debug( LDAP_DEBUG_TRACE, "wt_add: parent does not exist\n" );
rs->sr_err = LDAP_REFERRAL;
rs->sr_flags = REP_MATCHED_MUSTBEFREED | REP_REF_MUSTBEFREED;
goto return_results;
@ -173,8 +160,7 @@ wt_add( Operation *op, SlapReply *rs )
*/
p = NULL;
Debug( LDAP_DEBUG_TRACE,
LDAP_XSTRING(wt_add) ": no write access to parent\n" );
Debug( LDAP_DEBUG_TRACE, "wt_add: no write access to parent\n" );
rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
rs->sr_text = "no write access to parent";
goto return_results;;
@ -185,8 +171,7 @@ wt_add( Operation *op, SlapReply *rs )
wt_entry_return( p );
p = NULL;
/* parent is a subentry, don't allow add */
Debug( LDAP_DEBUG_TRACE,
LDAP_XSTRING(wt_add) ": parent is subentry\n" );
Debug( LDAP_DEBUG_TRACE, "wt_add: parent is subentry\n" );
rs->sr_err = LDAP_OBJECT_CLASS_VIOLATION;
rs->sr_text = "parent is a subentry";
goto return_results;;
@ -196,8 +181,7 @@ wt_add( Operation *op, SlapReply *rs )
wt_entry_return( p );
p = NULL;
/* parent is an alias, don't allow add */
Debug( LDAP_DEBUG_TRACE,
LDAP_XSTRING(wt_add) ": parent is alias\n" );
Debug( LDAP_DEBUG_TRACE, "wt_add: parent is alias\n" );
rs->sr_err = LDAP_ALIAS_PROBLEM;
rs->sr_text = "parent is an alias";
goto return_results;;
@ -213,8 +197,7 @@ wt_add( Operation *op, SlapReply *rs )
ber_bvarray_free( ref );
wt_entry_return( p );
p = NULL;
Debug( LDAP_DEBUG_TRACE,
LDAP_XSTRING(wt_add) ": parent is referral\n" );
Debug( LDAP_DEBUG_TRACE, "wt_add: parent is referral\n" );
rs->sr_err = LDAP_REFERRAL;
rs->sr_flags = REP_MATCHED_MUSTBEFREED | REP_REF_MUSTBEFREED;
@ -261,8 +244,7 @@ wt_add( Operation *op, SlapReply *rs )
entry, NULL, ACL_WADD, NULL );
if ( ! rs->sr_err ) {
Debug( LDAP_DEBUG_TRACE,
LDAP_XSTRING(wt_add) ": no write access to entry\n" );
Debug( LDAP_DEBUG_TRACE, "wt_add: no write access to entry\n" );
rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
rs->sr_text = "no write access to entry";
goto return_results;
@ -272,33 +254,29 @@ wt_add( Operation *op, SlapReply *rs )
* Check ACL for attribute write access
*/
if (!acl_check_modlist(op, op->ora_e, op->ora_modlist)) {
Debug( LDAP_DEBUG_TRACE,
LDAP_XSTRING(wt_add) ": no write access to attribute\n" );
Debug( LDAP_DEBUG_TRACE, "wt_add: no write access to attribute\n" );
rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
rs->sr_text = "no write access to attribute";
goto return_results;
}
rc = wc->session->begin_transaction(wc->session, NULL);
rc = wc->session->begin_transaction(wc->session, "isolation=read-uncommitted");
if( rc ) {
Debug( LDAP_DEBUG_TRACE,
LDAP_XSTRING(wt_add) ": begin_transaction failed: %s (%d)\n",
Debug( LDAP_DEBUG_TRACE, "wt_add: begin_transaction failed: %s (%d)\n",
wiredtiger_strerror(rc), rc );
rs->sr_err = LDAP_OTHER;
rs->sr_text = "begin_transaction failed";
goto return_results;
}
Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(wt_add) ": session id: %p\n",
wc->session );
Debug( LDAP_DEBUG_TRACE, "wt_add: session id: %p\n", wc->session );
wt_next_id( op->o_bd, &eid );
op->ora_e->e_id = eid;
rc = wt_dn2id_add( op, wc->session, pid, op->ora_e );
rc = wt_dn2id_add( op, wc, pid, op->ora_e );
if( rc ){
Debug( LDAP_DEBUG_TRACE,
LDAP_XSTRING(wt_add)
": dn2id_add failed: %s (%d)\n",
"wt_add: dn2id_add failed: %s (%d)\n",
wiredtiger_strerror(rc), rc );
switch( rc ) {
case WT_DUPLICATE_KEY:
@ -311,11 +289,10 @@ wt_add( Operation *op, SlapReply *rs )
goto return_results;
}
rc = wt_id2entry_add( op, wc->session, op->ora_e );
rc = wt_id2entry_add( op, wc, op->ora_e );
if ( rc ) {
Debug( LDAP_DEBUG_TRACE,
LDAP_XSTRING(wt_add)
": id2entry_add failed: %s (%d)\n",
"wt_add: id2entry_add failed: %s (%d)\n",
wiredtiger_strerror(rc), rc );
if ( rc == LDAP_ADMINLIMIT_EXCEEDED ) {
rs->sr_err = LDAP_ADMINLIMIT_EXCEEDED;
@ -332,8 +309,7 @@ wt_add( Operation *op, SlapReply *rs )
rc = wt_index_entry_add( op, wc, op->ora_e );
if ( rc ) {
Debug(LDAP_DEBUG_TRACE,
"<== " LDAP_XSTRING(wt_add)
": index add failed: %s (%d)\n",
"<== wt_add: index add failed: %s (%d)\n",
wiredtiger_strerror(rc), rc );
rs->sr_err = LDAP_OTHER;
rs->sr_text = "index add failed";
@ -344,8 +320,7 @@ wt_add( Operation *op, SlapReply *rs )
rc = wc->session->commit_transaction(wc->session, NULL);
if( rc ) {
Debug( LDAP_DEBUG_TRACE,
"<== " LDAP_XSTRING(wt_add)
": commit_transaction failed: %s (%d)\n",
"<== wt_add: commit_transaction failed: %s (%d)\n",
wiredtiger_strerror(rc), rc );
rs->sr_err = LDAP_OTHER;
rs->sr_text = "commit_transaction failed";
@ -363,9 +338,7 @@ wt_add( Operation *op, SlapReply *rs )
if ( slap_read_controls( op, rs, op->ora_e,
&slap_post_read_bv, postread_ctrl ) )
{
Debug( LDAP_DEBUG_TRACE,
"<=- " LDAP_XSTRING(wt_add) ": post-read "
"failed!\n" );
Debug( LDAP_DEBUG_TRACE, "<=- wt_add: post-read failed!\n" );
if ( op->o_postread & SLAP_CONTROL_CRITICAL ) {
/* FIXME: is it correct to abort
* operation if control fails? */
@ -375,12 +348,11 @@ wt_add( Operation *op, SlapReply *rs )
}
Debug(LDAP_DEBUG_TRACE,
LDAP_XSTRING(wt_add) ": added%s id=%08lx dn=\"%s\"\n",
"wt_add: added%s id=%08lx dn=\"%s\"\n",
op->o_noop ? " (no-op)" : "",
op->ora_e->e_id, op->ora_e->e_dn );
return_results:
success = rs->sr_err;
send_ldap_result( op, rs );
slap_graduate_commit_csn( op );

View file

@ -21,6 +21,7 @@
#include "back-wt.h"
#include "slap-config.h"
#include "lutil.h"
/* Find the ad, return -1 if not found,
* set point for insertion if ins is non-NULL
@ -57,7 +58,7 @@ wt_attr_slot( struct wt_info *wi, AttributeDescription *ad, int *ins )
static int
ainfo_insert( struct wt_info *wi, AttrInfo *a )
{
int x;
int x = INT_MAX;
int i = wt_attr_slot( wi, a->ai_desc, &x );
/* Is it a dup? */
@ -357,6 +358,44 @@ done:
return rc;
}
static int
wt_attr_index_unparser( void *v1, void *v2 )
{
AttrInfo *ai = v1;
BerVarray *bva = v2;
struct berval bv;
char *ptr;
slap_index2bvlen( ai->ai_indexmask, &bv );
if ( bv.bv_len ) {
bv.bv_len += ai->ai_desc->ad_cname.bv_len + 1;
ptr = ch_malloc( bv.bv_len+1 );
bv.bv_val = lutil_strcopy(ptr,
(const char*)ai->ai_desc->ad_cname.bv_val );
*bv.bv_val++ = ' ';
slap_index2bv( ai->ai_indexmask, &bv );
bv.bv_val = ptr;
ber_bvarray_add( bva, &bv );
}
return 0;
}
static AttributeDescription addef = { NULL, NULL, BER_BVC("default") };
static AttrInfo aidef = { &addef };
void
wt_attr_index_unparse( struct wt_info *wi, BerVarray *bva )
{
int i;
if ( wi->wi_defaultmask ) {
aidef.ai_indexmask = wi->wi_defaultmask;
wt_attr_index_unparser( &aidef, bva );
}
for ( i=0; i<wi->wi_nattrs; i++ )
wt_attr_index_unparser( wi->wi_attrs[i], bva );
}
void
wt_attr_info_free( AttrInfo *ai )
{
@ -377,8 +416,6 @@ wt_attr_index_destroy( struct wt_info *wi )
free( wi->wi_attrs );
}
/*
* Local variables:
* indent-tabs-mode: t

View file

@ -33,10 +33,13 @@
/* The default search IDL stack cache depth */
#define DEFAULT_SEARCH_STACK_DEPTH 16
#define WT_CONFIG_MAX 2048
struct wt_info {
WT_CONNECTION *wi_conn;
char *wi_dbenv_home;
char *wi_dbenv_config;
WT_CONNECTION *wi_cache;
char *wi_home;
char *wi_config;
ID wi_lastid;
slap_mask_t wi_defaultmask;
@ -53,23 +56,41 @@ struct wt_info {
#define WT_DEL_INDEX 0x08
#define WT_RE_OPEN 0x10
#define WT_NEED_UPGRADE 0x20
#define WT_USE_IDLCACHE 0x40
};
#define WT_TABLE_ID2ENTRY "table:id2entry"
#define WT_TABLE_DN2ID "table:dn2id"
#define WT_INDEX_DN "index:id2entry:dn"
#define WT_INDEX_NDN "index:dn2id:ndn"
#define WT_INDEX_PID "index:dn2id:pid"
/* Currently, revdn is primary key, the revdn index is obsolete. */
#define WT_INDEX_REVDN "index:dn2id:revdn"
/* table for cache */
#define WT_TABLE_IDLCACHE "table:idlcache"
#define ITEMzero(item) (memset((item), 0, sizeof(WT_ITEM)))
#define ITEM2bv(item,bv) ((bv)->bv_val = (item)->data, \
(bv)->bv_len = (item)->size)
#define bv2ITEM(bv,item) ((item)->data = (bv)->bv_val, \
(item)->size = (bv)->bv_len )
#define WT_INDEX_CACHE_SIZE 1024
typedef struct {
WT_SESSION *session;
int is_begin_transaction;
WT_CURSOR *dn2id;
WT_CURSOR *dn2id_w;
WT_CURSOR *dn2id_ndn;
WT_CURSOR *dn2entry;
WT_CURSOR *id2entry;
WT_CURSOR *id2entry_add;
WT_CURSOR *id2entry_update;
WT_SESSION *idlcache_session;
WT_CURSOR *index_pid;
} wt_ctx;
/* for the cache of attribute information (which are indexed, etc.) */

View file

@ -29,15 +29,13 @@ int
wt_bind( Operation *op, SlapReply *rs )
{
struct wt_info *wi = (struct wt_info *) op->o_bd->be_private;
WT_SESSION *session;
wt_ctx *wc;
int rc;
Entry *e = NULL;
Attribute *a;
AttributeDescription *password = slap_schema.si_ad_userPassword;
Debug( LDAP_DEBUG_ARGS,
"==> " LDAP_XSTRING(wt_bind) ": dn: %s\n",
Debug( LDAP_DEBUG_ARGS, "==> wt_bind: dn: %s\n",
op->o_req_dn.bv_val );
/* allow noauth binds */
@ -59,8 +57,7 @@ wt_bind( Operation *op, SlapReply *rs )
wc = wt_ctx_get(op, wi);
if( !wc ){
Debug( LDAP_DEBUG_ANY,
LDAP_XSTRING(wt_bind)
": wt_ctx_get failed\n" );
"wt_bind: wt_ctx_get failed\n" );
rs->sr_err = LDAP_OTHER;
rs->sr_text = "internal error";
send_ldap_result( op, rs );

View file

@ -0,0 +1,231 @@
/* OpenLDAP WiredTiger backend */
/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
*
* Copyright 2002-2017 The OpenLDAP Foundation.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted only as authorized by the OpenLDAP
* Public License.
*
* A copy of this license is available in the file LICENSE in the
* top-level directory of the distribution or, alternatively, at
* <http://www.OpenLDAP.org/license.html>.
*/
/* ACKNOWLEDGEMENTS:
* This work was developed by HAMANO Tsukasa <hamano@osstech.co.jp>
* based on back-bdb for inclusion in OpenLDAP Software.
* WiredTiger is a product of MongoDB Inc.
*/
#include "portable.h"
#include <stdio.h>
#include <ac/string.h>
#include "back-wt.h"
#include "slap-config.h"
#include "idl.h"
int wt_idlcache_get(wt_ctx *wc, struct berval *ndn, int scope, ID *ids)
{
int rc = 0;
WT_ITEM item;
WT_SESSION *session = wc->idlcache_session;
WT_CURSOR *cursor = NULL;
Debug( LDAP_DEBUG_TRACE,
"=> wt_idlcache_get(\"%s\", %d)\n",
ndn->bv_val, scope );
rc = session->open_cursor(session, WT_TABLE_IDLCACHE, NULL,
NULL, &cursor);
if(rc){
Debug( LDAP_DEBUG_ANY,
"wt_idlcache_get: open_cursor failed: %s (%d)\n",
wiredtiger_strerror(rc), rc );
return rc;
}
cursor->set_key(cursor, ndn->bv_val, (int8_t)scope);
rc = cursor->search(cursor);
switch( rc ){
case 0:
break;
case WT_NOTFOUND:
Debug(LDAP_DEBUG_TRACE, "<= wt_idlcache_get: miss\n" );
goto done;
default:
Debug( LDAP_DEBUG_ANY, "<= wt_idlcache_get: search failed: %s (%d)\n",
wiredtiger_strerror(rc), rc );
rc = 0;
goto done;
}
rc = cursor->get_value(cursor, &item);
if (rc) {
Debug( LDAP_DEBUG_ANY,
"wt_idlcache_get: get_value failed: %s (%d)\n",
wiredtiger_strerror(rc), rc );
goto done;
}
if (item.size == 0) {
Debug(LDAP_DEBUG_TRACE, "<= wt_idlcache_get: updating\n");
rc = WT_NOTFOUND;
goto done;
}
memcpy(ids, item.data, item.size);
Debug(LDAP_DEBUG_TRACE,
"<= wt_idlcache_get: hit id=%ld first=%ld last=%ld\n",
(long)ids[0],
(long)WT_IDL_FIRST(ids),
(long)WT_IDL_LAST(ids));
done:
if(cursor) {
cursor->close(cursor);
}
return rc;
}
int wt_idlcache_set(wt_ctx *wc, struct berval *ndn, int scope, ID *ids)
{
int rc = 0;
WT_ITEM item;
WT_SESSION *session = wc->idlcache_session;
WT_CURSOR *cursor = NULL;
Debug( LDAP_DEBUG_TRACE,
"=> wt_idlcache_set(\"%s\", %d)\n",
ndn->bv_val, scope );
item.size = WT_IDL_SIZEOF(ids);
item.data = ids;
rc = session->open_cursor(session, WT_TABLE_IDLCACHE, NULL,
"overwrite=false", &cursor);
if(rc){
Debug( LDAP_DEBUG_ANY,
"wt_idlcache_set: open_cursor failed: %s (%d)\n",
wiredtiger_strerror(rc), rc );
return rc;
}
cursor->set_key(cursor, ndn->bv_val, (int8_t)scope);
cursor->set_value(cursor, &item);
rc = cursor->update(cursor);
switch( rc ){
case 0:
break;
case WT_NOTFOUND:
// updating cache by another thread
goto done;
default:
Debug( LDAP_DEBUG_ANY,
"wt_idlcache_set: update failed: %s (%d)\n",
wiredtiger_strerror(rc), rc );
goto done;
}
Debug(LDAP_DEBUG_TRACE,
"<= wt_idlcache_set: set idl size=%ld\n",
(long)ids[0]);
done:
if(cursor) {
cursor->close(cursor);
}
return rc;
}
int wt_idlcache_begin(wt_ctx *wc, struct berval *ndn, int scope)
{
int rc = 0;
WT_ITEM item;
WT_SESSION *session = wc->idlcache_session;
WT_CURSOR *cursor = NULL;
Debug( LDAP_DEBUG_TRACE,
"=> wt_idlcache_begin(\"%s\", %d)\n",
ndn->bv_val, scope );
item.size = 0;
item.data = "";
rc = session->open_cursor(session, WT_TABLE_IDLCACHE, NULL,
"overwrite=true", &cursor);
if(rc){
Debug( LDAP_DEBUG_ANY,
"wt_idlcache_begin: open_cursor failed: %s (%d)\n",
wiredtiger_strerror(rc), rc );
return rc;
}
cursor->set_key(cursor, ndn->bv_val, (int8_t)scope);
cursor->set_value(cursor, &item);
rc = cursor->update(cursor);
if(rc){
Debug( LDAP_DEBUG_ANY,
"wt_idlcache_begin: update failed: %s (%d)\n",
wiredtiger_strerror(rc), rc );
goto done;
}
Debug(LDAP_DEBUG_TRACE,
"<= wt_idlcache_begin: set updating\n" );
done:
if(cursor) {
cursor->close(cursor);
}
return rc;
}
int wt_idlcache_clear(Operation *op, wt_ctx *wc, struct berval *ndn)
{
BackendDB *be = op->o_bd;
int rc = 0;
struct berval pdn = *ndn;
WT_SESSION *session = wc->idlcache_session;
WT_CURSOR *cursor = NULL;
int level = 0;
Debug( LDAP_DEBUG_TRACE,
"=> wt_idlcache_clear(\"%s\")\n",
ndn->bv_val );
if (be_issuffix( be, ndn )) {
return 0;
}
rc = session->open_cursor(session, WT_TABLE_IDLCACHE, NULL,
NULL, &cursor);
if(rc){
Debug( LDAP_DEBUG_ANY,
"wt_idlcache_clear: open_cursor failed: %s (%d)\n",
wiredtiger_strerror(rc), rc );
return rc;
}
do {
dnParent( &pdn, &pdn );
if (level == 0) {
/* clear only parent level cache */
cursor->set_key(cursor, pdn.bv_val, (int8_t)LDAP_SCOPE_ONE);
cursor->remove(cursor);
}
cursor->set_key(cursor, pdn.bv_val, (int8_t)LDAP_SCOPE_SUB);
cursor->remove(cursor);
cursor->set_key(cursor, pdn.bv_val, (int8_t)LDAP_SCOPE_CHILDREN);
cursor->remove(cursor);
level++;
}while(!be_issuffix( be, &pdn ));
if(cursor) {
cursor->close(cursor);
}
return 0;
}
/*
* Local variables:
* indent-tabs-mode: t
* tab-width: 4
* c-basic-offset: 4
* End:
*/

View file

@ -36,22 +36,20 @@ wt_compare( Operation *op, SlapReply *rs )
int rc;
wt_ctx *wc = NULL;
Debug( LDAP_DEBUG_ARGS, "==> " LDAP_XSTRING(wt_compare) ": %s\n",
Debug( LDAP_DEBUG_ARGS, "==> wt_compare: %s\n",
op->o_req_dn.bv_val );
wc = wt_ctx_get(op, wi);
if( !wc ){
Debug( LDAP_DEBUG_ANY,
LDAP_XSTRING(wt_compare)
": wt_ctx_get failed\n" );
Debug( LDAP_DEBUG_ANY, "wt_compare: wt_ctx_get failed\n" );
rs->sr_err = LDAP_OTHER;
rs->sr_text = "internal error";
send_ldap_result( op, rs );
return rs->sr_err;
}
rs->sr_err = wt_dn2entry(op->o_bd, wc, &op->o_req_ndn, &e);
switch( rs->sr_err ) {
rc = wt_dn2entry(op->o_bd, wc, &op->o_req_ndn, &e);
switch( rc ) {
case 0:
case WT_NOTFOUND:
break;
@ -61,37 +59,45 @@ wt_compare( Operation *op, SlapReply *rs )
goto return_results;
}
if ( rs->sr_err == WT_NOTFOUND ) {
if ( e != NULL ) {
/* return referral only if "disclose" is granted on the object */
if ( ! access_allowed( op, e, slap_schema.si_ad_entry,
NULL, ACL_DISCLOSE, NULL ) )
{
if ( rc == WT_NOTFOUND ||
(!manageDSAit && e && is_entry_glue( e ) )) {
if ( !e ) {
rc = wt_dn2aentry(op->o_bd, wc, &op->o_req_ndn, &e);
switch( rc ) {
case 0:
break;
case WT_NOTFOUND:
rs->sr_err = LDAP_NO_SUCH_OBJECT;
} else {
rs->sr_matched = ch_strdup( e->e_dn );
if ( is_entry_referral( e )) {
BerVarray ref = get_entry_referrals( op, e );
rs->sr_ref = referral_rewrite( ref,
&e->e_name,
&op->o_req_dn,
LDAP_SCOPE_DEFAULT );
ber_bvarray_free( ref );
} else {
rs->sr_ref = NULL;
}
rs->sr_err = LDAP_REFERRAL;
goto return_results;
default:
Debug( LDAP_DEBUG_ANY, "wt_compare: wt_dn2aentry failed (%d)\n",
rc );
rs->sr_err = LDAP_OTHER;
rs->sr_text = "internal error";
goto return_results;
}
wt_entry_return( e );
e = NULL;
} else {
rs->sr_ref = referral_rewrite( default_referral,
NULL,
&op->o_req_dn,
LDAP_SCOPE_DEFAULT );
rs->sr_err = rs->sr_ref ? LDAP_REFERRAL : LDAP_NO_SUCH_OBJECT;
}
/* return referral only if "disclose" is granted on the object */
if ( ! access_allowed( op, e, slap_schema.si_ad_entry,
NULL, ACL_DISCLOSE, NULL ) )
{
rs->sr_err = LDAP_NO_SUCH_OBJECT;
} else {
rs->sr_matched = ch_strdup( e->e_dn );
if ( is_entry_referral( e )) {
BerVarray ref = get_entry_referrals( op, e );
rs->sr_ref = referral_rewrite( ref,
&e->e_name,
&op->o_req_dn,
LDAP_SCOPE_DEFAULT );
ber_bvarray_free( ref );
} else {
rs->sr_ref = NULL;
}
rs->sr_err = LDAP_REFERRAL;
}
rs->sr_flags = REP_MATCHED_MUSTBEFREED | REP_REF_MUSTBEFREED;
send_ldap_result( op, rs );
goto done;

View file

@ -35,6 +35,8 @@ enum {
WT_DIRECTORY = 1,
WT_CONFIG,
WT_INDEX,
WT_MODE,
WT_IDLCACHE,
};
static ConfigTable wtcfg[] = {
@ -43,27 +45,35 @@ static ConfigTable wtcfg[] = {
"DESC 'Directory for database content' "
"EQUALITY caseIgnoreMatch "
"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
{ "wtconfig", "config", 2, 2, 0, ARG_STRING|ARG_MAGIC|WT_CONFIG,
wt_cf_gen, "( OLcfgDbAt:13.1 NAME 'olcWtConfig' "
"DESC 'Configuration for WiredTiger' "
"EQUALITY caseIgnoreMatch "
"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
{ "index", "attr> <[pres,eq,approx,sub]", 2, 3, 0, ARG_MAGIC|WT_INDEX,
wt_cf_gen, "( OLcfgDbAt:0.2 NAME 'olcDbIndex' "
"DESC 'Attribute index parameters' "
"EQUALITY caseIgnoreMatch "
"SYNTAX OMsDirectoryString )", NULL, NULL },
{ "mode", "mode", 2, 2, 0, ARG_MAGIC|WT_MODE,
wt_cf_gen, "( OLcfgDbAt:0.3 NAME 'olcDbMode' "
"DESC 'Unix permissions of database files' "
"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
{ "wtconfig", "config", 2, 2, 0, ARG_STRING|ARG_MAGIC|WT_CONFIG,
wt_cf_gen, "( OLcfgDbAt:13.1 NAME 'olcWtConfig' "
"DESC 'Configuration for WiredTiger' "
"EQUALITY caseIgnoreMatch "
"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
{ "idlcache", NULL, 1, 2, 0, ARG_ON_OFF|ARG_MAGIC|WT_IDLCACHE,
wt_cf_gen, "( OLcfgDbAt:13.2 NAME 'olcIDLcache' "
"DESC 'enable IDL cache' "
"SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
{ NULL, NULL, 0, 0, 0, ARG_IGNORED,
NULL, NULL, NULL, NULL }
};
static ConfigOCs wtocs[] = {
{ "( OLcfgDbOc:9.1 "
{ "( OLcfgDbOc:13.1 "
"NAME 'olcWtConfig' "
"DESC 'Wt backend configuration' "
"SUP olcDatabaseConfig "
"MUST olcDbDirectory "
"MAY ( olcWtConfig $ olcDbIndex ) )",
"MAY ( olcWtConfig $ olcDbIndex $ olcDbMode $ olcIDLcache) )",
Cft_Database, wtcfg },
{ NULL, 0, NULL }
};
@ -73,6 +83,7 @@ static void *
wt_online_index( void *ctx, void *arg )
{
// Not implement yet
return NULL;
}
/* Cleanup loose ends after Modify completes */
@ -89,20 +100,47 @@ wt_cf_gen( ConfigArgs *c )
struct wt_info *wi = (struct wt_info *) c->be->be_private;
int rc;
if(c->op == SLAP_CONFIG_EMIT) {
if( c->op == SLAP_CONFIG_EMIT ) {
rc = 0;
switch( c->type ) {
case WT_DIRECTORY:
if ( wi->wi_home ) {
c->value_string = ch_strdup( wi->wi_home );
} else {
rc = 1;
}
break;
case WT_INDEX:
wt_attr_index_unparse( wi, &c->rvalue_vals );
if ( !c->rvalue_vals ) rc = 1;
break;
case WT_IDLCACHE:
if ( wi->wi_flags & WT_USE_IDLCACHE) {
c->value_int = 1;
}
break;
}
return rc;
} else if ( c->op == LDAP_MOD_DELETE ) {
rc = 0;
// not implement yet
return rc;
}
switch( c->type ) {
case WT_DIRECTORY:
ch_free( wi->wi_dbenv_home );
wi->wi_dbenv_home = c->value_string;
ch_free( wi->wi_home );
wi->wi_home = c->value_string;
break;
case WT_CONFIG:
ch_free( wi->wi_dbenv_config );
wi->wi_dbenv_config = c->value_string;
if(strlen(wi->wi_config) + 1 + strlen(c->value_string) > WT_CONFIG_MAX){
fprintf( stderr, "%s: "
"\"wtconfig\" are too long. Increase WT_CONFIG_MAX or you may realloc the buffer.\n",
c->log );
return 1;
}
/* size of wi->wi_config is WT_CONFIG_MAX + 1, it's guaranteed with NUL-terminate. */
strcat(wi->wi_config, ",");
strcat(wi->wi_config, c->value_string);
break;
case WT_INDEX:
@ -135,6 +173,19 @@ wt_cf_gen( ConfigArgs *c )
}
break;
case WT_MODE:
fprintf( stderr, "%s: "
"back-wt does not support \"mode\" option. use umask instead.\n",
c->log );
return 1;
case WT_IDLCACHE:
if ( c->value_int ) {
wi->wi_flags |= WT_USE_IDLCACHE;
} else {
wi->wi_flags &= ~WT_USE_IDLCACHE;
}
break;
}
return LDAP_SUCCESS;
}

View file

@ -30,24 +30,32 @@ wt_ctx_init(struct wt_info *wi)
wc = ch_malloc( sizeof( wt_ctx ) );
if( !wc ) {
Debug( LDAP_DEBUG_ANY,
LDAP_XSTRING(wt_ctx_init)
": cannot allocate memory\n" );
Debug( LDAP_DEBUG_ANY, "wt_ctx_init: cannot allocate memory\n" );
return NULL;
}
memset(wc, 0, sizeof(wt_ctx));
if(!wc->session){
rc = wi->wi_conn->open_session(wi->wi_conn, NULL, NULL, &wc->session);
if( rc ) {
Debug( LDAP_DEBUG_ANY,
LDAP_XSTRING(wt_ctx_session)
": open_session error %s(%d)\n",
wiredtiger_strerror(rc), rc );
return NULL;
}
rc = wi->wi_conn->open_session(wi->wi_conn, NULL, NULL, &wc->session);
if( rc ) {
Debug( LDAP_DEBUG_ANY, "wt_ctx_init: open_session error %s(%d)\n",
wiredtiger_strerror(rc), rc );
return NULL;
}
/* readonly mode */
if (!wi->wi_cache) {
return wc;
}
rc = wi->wi_cache->open_session(wi->wi_cache, NULL, NULL, &wc->idlcache_session);
if( rc ) {
Debug( LDAP_DEBUG_ANY,
"wt_ctx_init: cannnot open idlcache session %s(%d)\n",
wiredtiger_strerror(rc), rc );
return NULL;
}
return wc;
}
@ -57,9 +65,19 @@ wt_ctx_free( void *key, void *data )
wt_ctx *wc = data;
if(wc->session){
wc->session->close(wc->session, NULL);
/*
* The session will close automatically when db closing.
* We can close session here, but it's require to check db
* status, otherwise it will cause SEGV.
*/
/*
if(IS_DB_OPEN) {
wc->session->close(wc->session, NULL);
}
*/
wc->session = NULL;
}
ch_free(wc);
}
@ -70,17 +88,15 @@ wt_ctx_get(Operation *op, struct wt_info *wi){
wt_ctx *wc = NULL;
rc = ldap_pvt_thread_pool_getkey(op->o_threadctx,
wt_ctx_get, &data, NULL );
wi, &data, NULL );
if( rc ){
wc = wt_ctx_init(wi);
if( !wc ) {
Debug( LDAP_DEBUG_ANY,
LDAP_XSTRING(wt_ctx)
": wt_ctx_init failed\n" );
Debug( LDAP_DEBUG_ANY, "wt_ctx: wt_ctx_init failed\n" );
return NULL;
}
rc = ldap_pvt_thread_pool_setkey( op->o_threadctx,
wt_ctx_get, wc, wt_ctx_free,
wi, wc, wt_ctx_free,
NULL, NULL );
if( rc ) {
Debug( LDAP_DEBUG_ANY, "wt_ctx: setkey error(%d)\n",
@ -92,45 +108,6 @@ wt_ctx_get(Operation *op, struct wt_info *wi){
return (wt_ctx *)data;
}
WT_CURSOR *
wt_ctx_index_cursor(wt_ctx *wc, struct berval *name, int create)
{
WT_CURSOR *cursor = NULL;
WT_SESSION *session = wc->session;
char tablename[1024];
int rc;
snprintf(tablename, sizeof(tablename), "table:%s", name->bv_val);
rc = session->open_cursor(session, tablename, NULL,
"overwrite=false", &cursor);
if (rc == ENOENT && create) {
rc = session->create(session,
tablename,
"key_format=uQ,"
"value_format=x,"
"columns=(key, id, none)");
if( rc ) {
Debug( LDAP_DEBUG_ANY,
LDAP_XSTRING(indexer) ": table \"%s\": "
"cannot create idnex table: %s (%d)\n",
tablename, wiredtiger_strerror(rc), rc);
return NULL;
}
rc = session->open_cursor(session, tablename, NULL,
"overwrite=false", &cursor);
}
if ( rc ) {
Debug( LDAP_DEBUG_ANY,
LDAP_XSTRING(wt_id2entry_put)
": open cursor failed: %s (%d)\n",
wiredtiger_strerror(rc), rc );
return NULL;
}
return cursor;
}
/*
* Local variables:
* indent-tabs-mode: t

View file

@ -44,12 +44,11 @@ wt_delete( Operation *op, SlapReply *rs )
wt_ctx *wc;
int rc;
WT_CURSOR *cursor = NULL;
int parent_is_glue = 0;
int parent_is_leaf = 0;
Debug( LDAP_DEBUG_ARGS, "==> " LDAP_XSTRING(wt_delete) ": %s\n",
Debug( LDAP_DEBUG_ARGS, "==> wt_delete: %s\n",
op->o_req_dn.bv_val );
if( op->o_txnSpec && txn_preop( op, rs ))
@ -60,9 +59,7 @@ wt_delete( Operation *op, SlapReply *rs )
wc = wt_ctx_get(op, wi);
if( !wc ){
Debug( LDAP_DEBUG_TRACE,
LDAP_XSTRING(wt_delete)
": wt_ctx_get failed\n" );
Debug( LDAP_DEBUG_TRACE, "wt_delete: wt_ctx_get failed\n" );
rs->sr_err = LDAP_OTHER;
rs->sr_text = "internal error";
goto return_results;
@ -89,26 +86,37 @@ wt_delete( Operation *op, SlapReply *rs )
case WT_NOTFOUND:
break;
default:
/* TODO: error handling */
rs->sr_err = LDAP_OTHER;
rs->sr_text = "internal error";
Debug( LDAP_DEBUG_ANY,
LDAP_XSTRING(wt_delete)
": error at wt_dn2entry() rc=%d\n",
rc );
"wt_delete: error at wt_dn2entry() rc=%d\n", rc );
goto return_results;
}
if ( rc == WT_NOTFOUND && pdn.bv_len != 0 ) {
Debug( LDAP_DEBUG_ARGS,
"<== " LDAP_XSTRING(wt_delete) ": no such object %s\n",
op->o_req_dn.bv_val );
"<== wt_delete: parent not found %s\n", op->o_req_dn.bv_val );
rc = wt_dn2aentry(op->o_bd, wc, &op->o_req_ndn, &e);
Debug( LDAP_DEBUG_ARGS, "<== wt_delete: rc=%d\n", rc );
if ( p && !BER_BVISEMPTY( &p->e_name )) {
rs->sr_matched = ch_strdup( p->e_name.bv_val );
if ( is_entry_referral( p )) {
BerVarray ref = get_entry_referrals( op, p );
rs->sr_ref = referral_rewrite( ref, &p->e_name,
switch( rc ) {
case 0:
break;
case WT_NOTFOUND:
rs->sr_err = LDAP_NO_SUCH_OBJECT;
goto return_results;
default:
Debug( LDAP_DEBUG_ANY, "wt_delete: wt_dn2aentry failed (%d)\n", rc );
rs->sr_err = LDAP_OTHER;
rs->sr_text = "internal error";
goto return_results;
}
if ( e && !BER_BVISEMPTY( &e->e_name )) {
rs->sr_matched = ch_strdup( e->e_name.bv_val );
if ( is_entry_referral( e )) {
BerVarray ref = get_entry_referrals( op, e );
rs->sr_ref = referral_rewrite( ref, &e->e_name,
&op->o_req_dn, LDAP_SCOPE_DEFAULT );
ber_bvarray_free( ref );
} else {
@ -130,30 +138,36 @@ wt_delete( Operation *op, SlapReply *rs )
case 0:
break;
case WT_NOTFOUND:
Debug( LDAP_DEBUG_ARGS,
"<== " LDAP_XSTRING(wt_delete)
": no such object %s\n",
op->o_req_dn.bv_val );
rs->sr_err = LDAP_REFERRAL;
rs->sr_flags = REP_MATCHED_MUSTBEFREED | REP_REF_MUSTBEFREED;
goto return_results;
break;
default:
/* TODO: error handling */
rs->sr_err = LDAP_OTHER;
rs->sr_text = "internal error";
Debug( LDAP_DEBUG_ANY,
LDAP_XSTRING(wt_delete)
": error at wt_dn2entry() rc=%d\n",
rc );
"wt_delete: error at wt_dn2entry() rc=%d\n", rc );
goto return_results;
}
/* FIXME : dn2entry() should return non-glue entry */
if ( !manageDSAit && is_entry_glue( e ) ) {
Debug( LDAP_DEBUG_ARGS,
"<== " LDAP_XSTRING(wt_delete)
": glue entry %s\n",
op->o_req_dn.bv_val );
if (rc == WT_NOTFOUND ||
( !manageDSAit && e && is_entry_glue( e ) )) {
if ( !e ) {
Debug( LDAP_DEBUG_ARGS,
"<== wt_delete: no such object %s\n",
op->o_req_dn.bv_val);
rc = wt_dn2aentry(op->o_bd, wc, &op->o_req_ndn, &e);
switch( rc ) {
case 0:
break;
case WT_NOTFOUND:
rs->sr_err = LDAP_NO_SUCH_OBJECT;
goto return_results;
default:
Debug( LDAP_DEBUG_ANY, "wt_delete: wt_dn2aentry failed (%d)\n", rc );
rs->sr_err = LDAP_OTHER;
rs->sr_text = "internal error";
goto return_results;
}
}
rs->sr_matched = ch_strdup( e->e_dn );
if ( is_entry_referral( e )) {
@ -177,8 +191,7 @@ wt_delete( Operation *op, SlapReply *rs )
if ( !rs->sr_err ) {
Debug( LDAP_DEBUG_TRACE,
"<== " LDAP_XSTRING(wt_delete) ": no write "
"access to parent\n" );
"<== wt_delete: no write access to parent\n" );
rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
rs->sr_text = "no write access to parent";
goto return_results;
@ -199,8 +212,7 @@ wt_delete( Operation *op, SlapReply *rs )
if ( !rs->sr_err ) {
Debug( LDAP_DEBUG_TRACE,
"<== " LDAP_XSTRING(wt_delete)
": no access to parent\n" );
"<== wt_delete: no access to parent\n" );
rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
rs->sr_text = "no write access to parent";
goto return_results;
@ -208,8 +220,7 @@ wt_delete( Operation *op, SlapReply *rs )
} else {
Debug( LDAP_DEBUG_TRACE,
"<== " LDAP_XSTRING(wt_delete)
": no parent and not root\n" );
"<== wt_delete: no parent and not root\n" );
rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
goto return_results;
}
@ -227,8 +238,7 @@ wt_delete( Operation *op, SlapReply *rs )
entry, NULL, ACL_WDEL, NULL );
if ( !rs->sr_err ) {
Debug( LDAP_DEBUG_TRACE,
"<== " LDAP_XSTRING(wt_delete) ": no write access "
"to entry\n" );
"<== wt_delete: no write access to entry\n" );
rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
rs->sr_text = "no write access to entry";
goto return_results;
@ -238,8 +248,7 @@ wt_delete( Operation *op, SlapReply *rs )
/* entry is a referral, don't allow delete */
rs->sr_ref = get_entry_referrals( op, e );
Debug( LDAP_DEBUG_TRACE,
LDAP_XSTRING(tw_delete) ": entry is referral\n" );
Debug( LDAP_DEBUG_TRACE, "wt_delete: entry is referral\n" );
rs->sr_err = LDAP_REFERRAL;
rs->sr_matched = ch_strdup( e->e_name.bv_val );
@ -257,8 +266,7 @@ wt_delete( Operation *op, SlapReply *rs )
&slap_pre_read_bv, preread_ctrl ) )
{
Debug( LDAP_DEBUG_TRACE,
"<== " LDAP_XSTRING(wt_delete) ": pre-read "
"failed!\n" );
"<== wt_delete: pre-read failed!\n" );
if ( op->o_preread & SLAP_CONTROL_CRITICAL ) {
/* FIXME: is it correct to abort
* operation if control fails? */
@ -268,21 +276,18 @@ wt_delete( Operation *op, SlapReply *rs )
}
/* Can't do it if we have kids */
rc = wt_dn2id_has_children( op, wc->session, e->e_id );
rc = wt_dn2id_has_children( op, wc, e->e_id );
if( rc != WT_NOTFOUND ) {
switch( rc ) {
case 0:
Debug(LDAP_DEBUG_ARGS,
"<== " LDAP_XSTRING(wt_delete)
": non-leaf %s\n",
op->o_req_dn.bv_val );
"<== wt_delete: non-leaf %s\n", op->o_req_dn.bv_val );
rs->sr_err = LDAP_NOT_ALLOWED_ON_NONLEAF;
rs->sr_text = "subordinate objects must be deleted first";
break;
default:
Debug(LDAP_DEBUG_ARGS,
"<== " LDAP_XSTRING(wt_delete)
": has_children failed: %s (%d)\n",
"<== wt_delete: has_children failed: %s (%d)\n",
wiredtiger_strerror(rc), rc );
rs->sr_err = LDAP_OTHER;
rs->sr_text = "internal error";
@ -294,7 +299,7 @@ wt_delete( Operation *op, SlapReply *rs )
rc = wc->session->begin_transaction(wc->session, NULL);
if( rc ) {
Debug( LDAP_DEBUG_TRACE,
LDAP_XSTRING(wt_add) ": begin_transaction failed: %s (%d)\n",
"wt_delete: begin_transaction failed: %s (%d)\n",
wiredtiger_strerror(rc), rc );
rs->sr_err = LDAP_OTHER;
rs->sr_text = "begin_transaction failed";
@ -302,11 +307,10 @@ wt_delete( Operation *op, SlapReply *rs )
}
/* delete from dn2id */
rc = wt_dn2id_delete( op, wc->session, &e->e_nname);
rc = wt_dn2id_delete( op, wc, &op->o_req_ndn);
if ( rc ) {
Debug(LDAP_DEBUG_TRACE,
"<== " LDAP_XSTRING(wt_delete)
": dn2id failed: %s (%d)\n",
"<== wt_delete: dn2id failed: %s (%d)\n",
wiredtiger_strerror(rc), rc );
rs->sr_err = LDAP_OTHER;
rs->sr_text = "dn2id delete failed";
@ -318,8 +322,7 @@ wt_delete( Operation *op, SlapReply *rs )
rc = wt_index_entry_del( op, wc, e );
if ( rc ) {
Debug(LDAP_DEBUG_TRACE,
"<== " LDAP_XSTRING(wt_delete)
": index delete failed: %s (%d)\n",
"<== wt_delete: index delete failed: %s (%d)\n",
wiredtiger_strerror(rc), rc );
rs->sr_err = LDAP_OTHER;
rs->sr_text = "index delete failed";
@ -334,7 +337,7 @@ wt_delete( Operation *op, SlapReply *rs )
assert( !BER_BVISNULL( &op->o_csn ) );
vals[0] = op->o_csn;
BER_BVZERO( &vals[1] );
rs->sr_err = wt_index_values( op, wc->session, slap_schema.si_ad_entryCSN,
rs->sr_err = wt_index_values( op, wc, slap_schema.si_ad_entryCSN,
vals, 0, SLAP_INDEX_ADD_OP );
if ( rs->sr_err != LDAP_SUCCESS ) {
rs->sr_text = "entryCSN index update failed";
@ -345,11 +348,10 @@ wt_delete( Operation *op, SlapReply *rs )
}
/* delete from id2entry */
rc = wt_id2entry_delete( op, wc->session, e );
rc = wt_id2entry_delete( op, wc, e );
if ( rc ) {
Debug( LDAP_DEBUG_TRACE,
"<== " LDAP_XSTRING(wt_delete)
": id2entry failed: %s (%d)\n",
"<== wt_delete: id2entry failed: %s (%d)\n",
wiredtiger_strerror(rc), rc );
rs->sr_err = LDAP_OTHER;
rs->sr_text = "entry delete failed";
@ -364,8 +366,7 @@ wt_delete( Operation *op, SlapReply *rs )
rc = wc->session->commit_transaction(wc->session, NULL);
if( rc ) {
Debug( LDAP_DEBUG_TRACE,
"<== " LDAP_XSTRING(wt_delete)
": commit_transaction failed: %s (%d)\n",
"<== wt_delete: commit_transaction failed: %s (%d)\n",
wiredtiger_strerror(rc), rc );
rs->sr_err = LDAP_OTHER;
rs->sr_text = "commit_transaction failed";
@ -373,8 +374,7 @@ wt_delete( Operation *op, SlapReply *rs )
}
Debug( LDAP_DEBUG_TRACE,
LDAP_XSTRING(wt_delete)
": deleted%s id=%08lx dn=\"%s\"\n",
"wt_delete: deleted%s id=%08lx dn=\"%s\"\n",
op->o_noop ? " (no-op)" : "", e->e_id, op->o_req_dn.bv_val );
rs->sr_err = LDAP_SUCCESS;

View file

@ -35,28 +35,33 @@ int wt_dn2entry( BackendDB *be,
struct berval *ndn,
Entry **ep ){
uint64_t id;
WT_CURSOR *cursor = NULL;
WT_ITEM item;
EntryHeader eh;
int rc;
int eoff;
Entry *e = NULL;
WT_SESSION *session = wc->session;
WT_CURSOR *cursor = wc->dn2entry;
if( ndn->bv_len == 0 ){
/* parent of root dn */
return WT_NOTFOUND;
/* empty dn */
e = entry_alloc();
ber_dupbv(&e->e_nname, ndn);
*ep = e;
return LDAP_SUCCESS;
}
rc = session->open_cursor(session,
WT_INDEX_DN"(id, entry)",
NULL, NULL, &cursor);
if ( rc ) {
Debug( LDAP_DEBUG_ANY,
LDAP_XSTRING(wt_dn2entry)
": open_cursor failed: %s (%d)\n",
wiredtiger_strerror(rc), rc );
goto done;
if(!cursor){
rc = session->open_cursor(session,
WT_INDEX_DN"(id, entry)",
NULL, NULL, &cursor);
if ( rc ) {
Debug( LDAP_DEBUG_ANY,
"wt_dn2entry: open_cursor failed: %s (%d)\n",
wiredtiger_strerror(rc), rc );
goto done;
}
wc->dn2entry = cursor;
}
cursor->set_key(cursor, ndn->bv_val);
@ -68,8 +73,7 @@ int wt_dn2entry( BackendDB *be,
goto done;
default:
Debug( LDAP_DEBUG_ANY,
LDAP_XSTRING(wt_dn2entry)
": search failed: %s (%d)\n",
"wt_dn2entry: search failed: %s (%d)\n",
wiredtiger_strerror(rc), rc );
goto done;
}
@ -86,9 +90,7 @@ int wt_dn2entry( BackendDB *be,
rc = entry_decode( &eh, &e );
if ( rc ) {
Debug( LDAP_DEBUG_ANY,
LDAP_XSTRING(wt_dn2entry)
": entry decode error: %d\n",
rc );
"wt_dn2entry: entry decode error: %d\n", rc );
goto done;
}
@ -96,9 +98,17 @@ int wt_dn2entry( BackendDB *be,
*ep = e;
done:
#ifdef WT_CURSOR_CACHE
if(cursor){
cursor->reset(cursor);
}
#else
if(cursor){
cursor->close(cursor);
wc->dn2entry = NULL;
}
#endif
return rc;
}
@ -122,6 +132,41 @@ int wt_dn2pentry( BackendDB *be,
return rc;
}
/* dn2aentry - return ancestor entry */
int wt_dn2aentry( BackendDB *be,
wt_ctx *wc,
struct berval *ndn,
Entry **ep ) {
Entry *e = NULL;
struct berval pdn;
int rc;
if (be_issuffix( be, ndn )) {
*ep = NULL;
return 0;
}
dnParent( ndn, &pdn );
rc = wt_dn2entry(be, wc, &pdn, &e);
switch( rc ) {
case 0:
*ep = e;
break;
case WT_NOTFOUND:
rc = wt_dn2aentry(be, wc, &pdn, &e);
if (rc != 0 && rc != WT_NOTFOUND) {
return rc;
}
*ep = e;
break;
default:
Debug( LDAP_DEBUG_ANY,
"wt_dn2aentry: failed %s (%d)\n",
wiredtiger_strerror(rc), rc );
}
return rc;
}
/*
* Local variables:
* indent-tabs-mode: t

View file

@ -26,7 +26,7 @@
#include "slap-config.h"
#include "idl.h"
char *
static char *
mkrevdn(struct berval src){
char *dst, *p;
char *rdn;
@ -46,7 +46,7 @@ mkrevdn(struct berval src){
rdn = src.bv_val;
src.bv_len = 0;
}
AC_MEMCPY( p, rdn, rdn_len );
memcpy( p, rdn, rdn_len );
p += rdn_len;
*p++ = ',';
}
@ -57,12 +57,14 @@ mkrevdn(struct berval src){
int
wt_dn2id_add(
Operation *op,
WT_SESSION *session,
wt_ctx *wc,
ID pid,
Entry *e)
{
struct wt_info *wi = (struct wt_info *) op->o_bd->be_private;
int rc;
WT_CURSOR *cursor = NULL;
WT_SESSION *session = wc->session;
WT_CURSOR *cursor = wc->dn2id_w;
char *revdn = NULL;
Debug( LDAP_DEBUG_TRACE, "=> wt_dn2id_add 0x%lx: \"%s\"\n",
@ -72,33 +74,47 @@ wt_dn2id_add(
/* make reverse dn */
revdn = mkrevdn(e->e_nname);
rc = session->open_cursor(session, WT_TABLE_DN2ID, NULL,
NULL, &cursor);
if(rc){
Debug( LDAP_DEBUG_ANY,
LDAP_XSTRING(wt_dn2id_add)
": open_cursor failed: %s (%d)\n",
wiredtiger_strerror(rc), rc );
goto done;
}
cursor->set_key(cursor, e->e_ndn);
cursor->set_value(cursor, e->e_id, pid, revdn);
if(!cursor){
rc = session->open_cursor(session, WT_TABLE_DN2ID, NULL,
"overwrite=false", &cursor);
if(rc){
Debug( LDAP_DEBUG_ANY,
"wt_dn2id_add: open_cursor failed: %s (%d)\n",
wiredtiger_strerror(rc), rc );
goto done;
}
wc->dn2id_w = cursor;
}
cursor->set_key(cursor, revdn);
cursor->set_value(cursor, e->e_ndn, e->e_id, pid);
rc = cursor->insert(cursor);
if(rc){
Debug( LDAP_DEBUG_ANY,
LDAP_XSTRING(wt_dn2id_add)
": insert failed: %s (%d)\n",
"wt_dn2id_add: insert failed: %s (%d)\n",
wiredtiger_strerror(rc), rc );
goto done;
}
if (wi->wi_flags & WT_USE_IDLCACHE) {
wt_idlcache_clear(op, wc, &e->e_nname);
}
done:
if(revdn){
ch_free(revdn);
}
#ifdef WT_CURSOR_CACHE
if(cursor){
cursor->reset(cursor);
}
#else
if(cursor){
cursor->close(cursor);
wc->dn2id_w = NULL;
}
#endif
Debug( LDAP_DEBUG_TRACE, "<= wt_dn2id_add 0x%lx: %d\n", e->e_id, rc );
return rc;
}
@ -106,73 +122,94 @@ done:
int
wt_dn2id_delete(
Operation *op,
WT_SESSION *session,
wt_ctx *wc,
struct berval *ndn)
{
struct wt_info *wi = (struct wt_info *) op->o_bd->be_private;
int rc = 0;
WT_CURSOR *cursor = NULL;
WT_SESSION *session = wc->session;
WT_CURSOR *cursor = wc->dn2id_w;
char *revdn = NULL;
Debug( LDAP_DEBUG_TRACE, "=> wt_dn2id_delete %s\n", ndn->bv_val );
rc = session->open_cursor(session, WT_TABLE_DN2ID, NULL,
NULL, &cursor);
if ( rc ) {
Debug( LDAP_DEBUG_ANY,
LDAP_XSTRING(wt_dn2id_delete)
": open_cursor failed: %s (%d)\n",
wiredtiger_strerror(rc), rc );
goto done;
/* make reverse dn */
revdn = mkrevdn(*ndn);
if(!cursor){
rc = session->open_cursor(session, WT_TABLE_DN2ID, NULL,
"overwrite=false", &cursor);
if ( rc ) {
Debug( LDAP_DEBUG_ANY,
"wt_dn2id_delete: open_cursor failed: %s (%d)\n",
wiredtiger_strerror(rc), rc );
goto done;
}
wc->dn2id_w = cursor;
}
cursor->set_key(cursor, ndn->bv_val);
cursor->set_key(cursor, revdn);
rc = cursor->remove(cursor);
if ( rc ) {
Debug( LDAP_DEBUG_ANY,
LDAP_XSTRING(wt_dn2id_delete)
": remove failed: %s (%d)\n",
"wt_dn2id_delete: remove failed: %s (%d)\n",
wiredtiger_strerror(rc), rc );
goto done;
}
if (wi->wi_flags & WT_USE_IDLCACHE) {
wt_idlcache_clear(op, wc, ndn);
}
Debug( LDAP_DEBUG_TRACE,
"<= wt_dn2id_delete %s: %d\n",
ndn->bv_val, rc );
"<= wt_dn2id_delete %s: %d\n", ndn->bv_val, rc );
done:
if(revdn){
ch_free(revdn);
}
#ifdef WT_CURSOR_CACHE
if(cursor){
cursor->reset(cursor);
}
#else
if(cursor){
cursor->close(cursor);
wc->dn2id_w = NULL;
}
#endif
return rc;
}
int
wt_dn2id(
Operation *op,
WT_SESSION *session,
wt_ctx *wc,
struct berval *ndn,
ID *id)
{
WT_CURSOR *cursor = NULL;
struct wt_info *wi = (struct wt_info *) op->o_bd->be_private;
int rc;
ID nid;
WT_SESSION *session = wc->session;
WT_CURSOR *cursor = wc->dn2id_ndn;
int rc = LDAP_SUCCESS;
Debug( LDAP_DEBUG_TRACE, "=> wt_dn2id(\"%s\")\n",
ndn->bv_val );
Debug( LDAP_DEBUG_TRACE, "=> wt_dn2id(\"%s\")\n", ndn->bv_val );
if ( ndn->bv_len == 0 ) {
*id = 0;
goto done;
}
rc = session->open_cursor(session, WT_TABLE_DN2ID
"(id)",
NULL, NULL, &cursor);
if( rc ){
Debug( LDAP_DEBUG_ANY,
LDAP_XSTRING(wt_dn2id)
": cursor open failed: %s (%d)\n",
wiredtiger_strerror(rc), rc );
goto done;
if(!cursor){
rc = session->open_cursor(session, WT_INDEX_NDN
"(id)",
NULL, NULL, &cursor);
if( rc ){
Debug( LDAP_DEBUG_ANY,
"wt_dn2id: cursor open failed: %s (%d)\n",
wiredtiger_strerror(rc), rc );
goto done;
}
wc->dn2id_ndn = cursor;
}
cursor->set_key(cursor, ndn->bv_val);
@ -184,24 +221,30 @@ wt_dn2id(
goto done;
default:
Debug( LDAP_DEBUG_ANY,
LDAP_XSTRING(wt_dn2id)
": search failed: %s (%d)\n",
"wt_dn2id: search failed: %s (%d)\n",
wiredtiger_strerror(rc), rc );
goto done;
}
rc = cursor->get_value(cursor, id);
if( rc ){
Debug( LDAP_DEBUG_ANY,
LDAP_XSTRING(wt_dn2id)
": get_value failed: %s (%d)\n",
"wt_dn2id: get_value failed: %s (%d)\n",
wiredtiger_strerror(rc), rc );
goto done;
}
done:
#ifdef WT_CURSOR_CACHE
if(cursor){
cursor->reset(cursor);
}
#else
if(cursor){
cursor->close(cursor);
wc->dn2id_ndn = NULL;
}
#endif
if( rc ) {
Debug( LDAP_DEBUG_TRACE, "<= wt_dn2id: get failed: %s (%d)\n",
@ -217,47 +260,56 @@ done:
int
wt_dn2id_has_children(
Operation *op,
WT_SESSION *session,
wt_ctx *wc,
ID id )
{
struct wt_info *wi = (struct wt_info *) op->o_bd->be_private;
WT_CURSOR *cursor = NULL;
WT_SESSION *session = wc->session;
WT_CURSOR *cursor = wc->index_pid;
int rc;
uint64_t key = id;
rc = session->open_cursor(session, WT_INDEX_PID,
NULL, NULL, &cursor);
if( rc ){
Debug( LDAP_DEBUG_ANY,
LDAP_XSTRING(wt_dn2id_has_children)
": cursor open failed: %s (%d)\n",
wiredtiger_strerror(rc), rc );
goto done;
if(!cursor){
rc = session->open_cursor(session, WT_INDEX_PID,
NULL, NULL, &cursor);
if( rc ){
Debug( LDAP_DEBUG_ANY,
"wt_dn2id_has_children: cursor open failed: %s (%d)\n",
wiredtiger_strerror(rc), rc );
goto done;
}
wc->index_pid = cursor;
}
cursor->set_key(cursor, key);
rc = cursor->search(cursor);
done:
#ifdef WT_CURSOR_CACHE
if(cursor){
cursor->reset(cursor);
}
#else
if(cursor){
cursor->close(cursor);
wc->index_pid = NULL;
}
#endif
return rc;
}
int
wt_dn2idl(
wt_dn2idl_db(
Operation *op,
WT_SESSION *session,
wt_ctx *wc,
struct berval *ndn,
Entry *e,
ID *ids,
ID *stack)
{
struct wt_info *wi = (struct wt_info *) op->o_bd->be_private;
WT_CURSOR *cursor = NULL;
int exact = 0;
WT_SESSION *session = wc->session;
WT_CURSOR *cursor = wc->dn2id;
int rc;
char *revdn = NULL;
size_t revdn_len;
@ -268,73 +320,58 @@ wt_dn2idl(
"=> wt_dn2idl(\"%s\")\n",
ndn->bv_val );
if(op->ors_scope != LDAP_SCOPE_ONELEVEL &&
be_issuffix( op->o_bd, &e->e_nname )){
WT_IDL_ALL(wi, ids);
return 0;
}
revdn = mkrevdn(*ndn);
revdn_len = strlen(revdn);
rc = session->open_cursor(session, WT_INDEX_REVDN"(id, pid)",
NULL, NULL, &cursor);
if ( !cursor ) {
rc = session->open_cursor(session, WT_TABLE_DN2ID"(id, pid)",
NULL, NULL, &cursor);
if( rc ){
Debug( LDAP_DEBUG_ANY,
"wt_dn2idl: cursor open failed: %s (%d)\n",
wiredtiger_strerror(rc), rc );
goto done;
}
wc->dn2id = cursor;
}
cursor->set_key(cursor, revdn);
rc = cursor->search(cursor);
if( rc ){
Debug( LDAP_DEBUG_ANY,
LDAP_XSTRING(wt_dn2idl)
": cursor open failed: %s (%d)\n",
"wt_dn2idl: search failed: %s (%d)\n",
wiredtiger_strerror(rc), rc );
goto done;
}
cursor->set_key(cursor, revdn);
rc = cursor->search_near(cursor, &exact);
if( rc ){
Debug( LDAP_DEBUG_ANY,
LDAP_XSTRING(wt_dn2idl)
": search failed: %s (%d)\n",
wiredtiger_strerror(rc), rc );
goto done;
if( op->ors_scope == LDAP_SCOPE_CHILDREN ) {
cursor->next(cursor);
}
do {
rc = cursor->get_key(cursor, &key);
if( rc ){
Debug( LDAP_DEBUG_ANY,
LDAP_XSTRING(wt_dn2idl)
": get_key failed: %s (%d)\n",
"wt_dn2idl: get_key failed: %s (%d)\n",
wiredtiger_strerror(rc), rc );
goto done;
}
rc = cursor->get_value(cursor, &id, &pid);
if( rc ){
Debug( LDAP_DEBUG_ANY,
"wt_dn2id: get_value failed: %s (%d)\n",
wiredtiger_strerror(rc), rc );
goto done;
}
if( strncmp(revdn, key, revdn_len) ){
if(exact < 0){
rc = cursor->next(cursor);
if (rc) {
break;
}else{
continue;
}
}
break;
}
exact = 0;
rc = cursor->get_value(cursor, &id, &pid);
if( rc ){
Debug( LDAP_DEBUG_ANY,
LDAP_XSTRING(wt_dn2id)
": get_value failed: %s (%d)\n",
wiredtiger_strerror(rc), rc );
goto done;
}
if( op->ors_scope == LDAP_SCOPE_ONELEVEL &&
e->e_id != pid){
rc = cursor->next(cursor);
if ( rc ) {
break;
}
continue;
}else{
wt_idl_append_one(ids, id);
if( op->ors_scope == LDAP_SCOPE_ONELEVEL && e->e_id != pid ){
goto next;
}
wt_idl_append_one(ids, id);
next:
rc = cursor->next(cursor);
}while(rc == 0);
@ -342,47 +379,70 @@ wt_dn2idl(
rc = LDAP_SUCCESS;
}
wt_idl_sort(ids, stack);
Debug( LDAP_DEBUG_TRACE,
"<= wt_dn2idl_db: size=%ld first=%ld last=%ld\n",
(long) ids[0],
(long) WT_IDL_FIRST(ids),
(long) WT_IDL_LAST(ids) );
done:
if(revdn){
ch_free(revdn);
}
#ifdef WT_CURSOR_CACHE
if(cursor){
cursor->reset(cursor);
}
#else
if(cursor){
cursor->close(cursor);
wc->dn2id = NULL;
}
return rc;
}
#if 0
int
wt_dn2id(
Operation *op,
WT_SESSION *session,
struct berval *dn,
ID *id)
{
struct wt_info *wi = (struct wy_info *) op->o_bd->be_private;
WT_CURSOR *cursor = NULL;
int rc;
Debug( LDAP_DEBUG_TRACE, "=> wt_dn2id(\"%s\")\n", dn->bv_val );
rc = session->open_cursor(session, WT_INDEX_DN"(id)",
NULL, NULL, &cursor);
if( rc ){
Debug( LDAP_DEBUG_ANY,
LDAP_XSTRING(wt_dn2id)
": cursor open failed: %s (%d)\n",
wiredtiger_strerror(rc), rc );
return rc;
}
cursor->set_key(cursor, dn->bv_val);
rc = cursor->search(cursor);
if( !rc ){
cursor->get_key(cursor, &id);
}
cursor->close(cursor);
return rc;
}
#endif
return rc;
}
int
wt_dn2idl(
Operation *op,
wt_ctx *wc,
struct berval *ndn,
Entry *e,
ID *ids,
ID *stack)
{
struct wt_info *wi = (struct wt_info *) op->o_bd->be_private;
int rc;
Debug( LDAP_DEBUG_TRACE,
"=> wt_dn2idl(\"%s\")\n", ndn->bv_val );
if(op->ors_scope != LDAP_SCOPE_ONELEVEL &&
be_issuffix( op->o_bd, &e->e_nname )){
WT_IDL_ALL(wi, ids);
return 0;
}
if (wi->wi_flags & WT_USE_IDLCACHE) {
rc = wt_idlcache_get(wc, ndn, op->ors_scope, ids);
if (rc == 0) {
/* cache hit */
return rc;
}
/* cache miss */
}
if ( wi->wi_flags & WT_USE_IDLCACHE ) {
wt_idlcache_begin(wc, ndn, op->ors_scope);
}
rc = wt_dn2idl_db(op, wc, ndn, e, ids, stack);
if ( rc == 0 && wi->wi_flags & WT_USE_IDLCACHE ) {
wt_idlcache_set(wc, ndn, op->ors_scope, ids);
}
return rc;
}
/*
* Local variables:

View file

@ -0,0 +1,58 @@
/* OpenLDAP WiredTiger backend */
/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
*
* Copyright 2002-2015 The OpenLDAP Foundation.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted only as authorized by the OpenLDAP
* Public License.
*
* A copy of this license is available in the file LICENSE in the
* top-level directory of the distribution or, alternatively, at
* <http://www.OpenLDAP.org/license.html>.
*/
/* ACKNOWLEDGEMENTS:
* This work was developed by HAMANO Tsukasa <hamano@osstech.co.jp>
* based on back-bdb for inclusion in OpenLDAP Software.
* WiredTiger is a product of MongoDB Inc.
*/
#include "portable.h"
#include <stdio.h>
#include <ac/string.h>
#include "back-wt.h"
#include "lber_pvt.h"
static struct exop {
struct berval *oid;
BI_op_extended *extended;
} exop_table[] = {
{ NULL, NULL }
};
int
wt_extended( Operation *op, SlapReply *rs )
{
int i;
for( i=0; exop_table[i].extended != NULL; i++ ) {
if( ber_bvcmp( exop_table[i].oid, &op->oq_extended.rs_reqoid ) == 0 ) {
return (exop_table[i].extended)( op, rs );
}
}
rs->sr_text = "not supported within naming context";
return rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
}
/*
* Local variables:
* indent-tabs-mode: t
* tab-width: 4
* c-basic-offset: 4
* End:
*/

View file

@ -75,7 +75,7 @@ presence_candidates(
}
/* open index cursor */
cursor = wt_ctx_index_cursor(wc, &desc->ad_type->sat_cname, 0);
cursor = wt_index_open(wc, &desc->ad_type->sat_cname, 0);
if( !cursor ) {
Debug( LDAP_DEBUG_ANY,
"<= wt_presence_candidates: open index cursor failed: %s\n",
@ -85,9 +85,7 @@ presence_candidates(
rc = wt_key_read( op->o_bd, cursor, &prefix, ids, NULL, 0 );
if(cursor){
cursor->close(cursor);
}
cursor->close(cursor);
Debug(LDAP_DEBUG_TRACE,
"<= wt_presence_candidates: id=%ld first=%ld last=%ld\n",
(long) ids[0],
@ -114,12 +112,12 @@ equality_candidates(
MatchingRule *mr;
WT_CURSOR *cursor = NULL;
Debug( LDAP_DEBUG_TRACE, "=> wt_equality_candidates (%s)\n",
ava->aa_desc->ad_cname.bv_val );
Debug( LDAP_DEBUG_TRACE, "=> wt_equality_candidates (%s=%s)\n",
ava->aa_desc->ad_cname.bv_val, ava->aa_value.bv_val );
if ( ava->aa_desc == slap_schema.si_ad_entryDN ) {
ID id = NOID;
rc = wt_dn2id(op, wc->session, &ava->aa_value, &id);
rc = wt_dn2id(op, wc, &ava->aa_value, &id);
if( rc == 0 ){
wt_idl_append_one(ids, id);
}else if ( rc == WT_NOTFOUND ) {
@ -182,7 +180,7 @@ equality_candidates(
}
/* open index cursor */
cursor = wt_ctx_index_cursor(wc, &ava->aa_desc->ad_type->sat_cname, 0);
cursor = wt_index_open(wc, &ava->aa_desc->ad_type->sat_cname, 0);
if( !cursor ) {
Debug( LDAP_DEBUG_ANY,
"<= wt_equality_candidates: open index cursor failed: %s\n",
@ -198,8 +196,7 @@ equality_candidates(
break;
} else if( rc != LDAP_SUCCESS ) {
Debug( LDAP_DEBUG_TRACE,
"<= wt_equality_candidates: (%s) "
"key read failed (%d)\n",
"<= wt_equality_candidates: (%s) key read failed (%d)\n",
ava->aa_desc->ad_cname.bv_val, rc );
break;
}
@ -215,9 +212,7 @@ equality_candidates(
ber_bvarray_free_x( keys, op->o_tmpmemctx );
if(cursor){
cursor->close(cursor);
}
cursor->close(cursor);
Debug( LDAP_DEBUG_TRACE,
"<= wt_equality_candidates: id=%ld, first=%ld, last=%ld\n",
@ -305,7 +300,7 @@ approx_candidates(
}
/* open index cursor */
cursor = wt_ctx_index_cursor(wc, &ava->aa_desc->ad_type->sat_cname, 0);
cursor = wt_index_open(wc, &ava->aa_desc->ad_type->sat_cname, 0);
if( !cursor ) {
Debug( LDAP_DEBUG_ANY,
"<= wt_approx_candidates: open index cursor failed: %s\n",
@ -346,9 +341,7 @@ approx_candidates(
ber_bvarray_free_x( keys, op->o_tmpmemctx );
if(cursor){
cursor->close(cursor);
}
cursor->close(cursor);
Debug( LDAP_DEBUG_TRACE,
"<= wt_approx_candidates %ld, first=%ld, last=%ld\n",
@ -393,8 +386,7 @@ substring_candidates(
if( rc != LDAP_SUCCESS ) {
Debug( LDAP_DEBUG_ANY,
"<= wt_substring_candidates: (%s) "
"index_param failed (%d)\n",
"<= wt_substring_candidates: (%s) index_param failed (%d)\n",
sub->sa_desc->ad_cname.bv_val, rc );
return 0;
}
@ -433,7 +425,7 @@ substring_candidates(
}
/* open index cursor */
cursor = wt_ctx_index_cursor(wc, &sub->sa_desc->ad_cname, 0);
cursor = wt_index_open(wc, &sub->sa_desc->ad_cname, 0);
if( !cursor ) {
Debug( LDAP_DEBUG_ANY,
"<= wt_substring_candidates: open index cursor failed: %s\n",
@ -475,9 +467,7 @@ substring_candidates(
ber_bvarray_free_x( keys, op->o_tmpmemctx );
if(cursor){
cursor->close(cursor);
}
cursor->close(cursor);
Debug( LDAP_DEBUG_TRACE,
"<= wt_substring_candidates: %ld, first=%ld, last=%ld\n",
@ -487,6 +477,56 @@ substring_candidates(
return rc;
}
#ifdef LDAP_COMP_MATCH
static int
comp_candidates (
Operation *op,
wt_ctx *wc,
MatchingRuleAssertion *mra,
ComponentFilter *f,
ID *ids,
ID *tmp,
ID *stack)
{
int rc = 0;
if ( !f ) return LDAP_PROTOCOL_ERROR;
Debug( LDAP_DEBUG_FILTER, "comp_candidates\n" );
/* TODO: */
Debug( LDAP_DEBUG_FILTER, "=> not implement yet\n" );
return( rc );
}
#endif
static int
ext_candidates(
Operation *op,
wt_ctx *wc,
MatchingRuleAssertion *mra,
ID *ids,
ID *tmp,
ID *stack )
{
struct wt_info *wi = (struct wt_info *) op->o_bd->be_private;
#ifdef LDAP_COMP_MATCH
/*
* Currently Only Component Indexing for componentFilterMatch is supported
* Indexing for an extensible filter is not supported yet
*/
if ( mra->ma_cf ) {
return comp_candidates ( op, wc, mra, mra->ma_cf, ids, tmp, stack);
}
#endif
if ( mra->ma_desc == slap_schema.si_ad_entryDN ) {
/* TODO: */
Debug( LDAP_DEBUG_FILTER, "=> not implement yet.\n" );
}
WT_IDL_ALL( wi, ids );
return 0;
}
static int
list_candidates(
@ -569,7 +609,7 @@ wt_filter_candidates(
ID *stack )
{
struct wt_info *wi = (struct wt_info *)op->o_bd->be_private;
int rc = 0;
int rc = LDAP_SUCCESS;
Debug( LDAP_DEBUG_FILTER, "=> wt_filter_candidates\n" );
if ( f->f_choice & SLAPD_FILTER_UNDEFINED ) {
@ -649,9 +689,8 @@ wt_filter_candidates(
break;
case LDAP_FILTER_EXT:
/* TODO: not implement yet */
Debug( LDAP_DEBUG_FILTER, "\tEXT\n" );
rc = presence_candidates( op, wc, f->f_ava->aa_desc, ids );
rc = ext_candidates( op, wc, f->f_mra, ids, tmp, stack);
break;
default:
@ -667,7 +706,7 @@ done:
(long) ids[0],
(long) WT_IDL_FIRST( ids ),
(long) WT_IDL_LAST( ids ) );
return 0;
return rc;
}
/*

View file

@ -24,12 +24,11 @@
static int wt_id2entry_put(
Operation *op,
WT_SESSION *session,
wt_ctx *wc,
Entry *e,
const char *config )
WT_CURSOR *cursor)
{
struct berval bv;
WT_CURSOR *cursor = NULL;
WT_ITEM item;
int rc;
@ -40,63 +39,108 @@ static int wt_id2entry_put(
item.size = bv.bv_len;
item.data = bv.bv_val;
rc = session->open_cursor(session, WT_TABLE_ID2ENTRY, NULL,
config, &cursor);
if ( rc ) {
Debug( LDAP_DEBUG_ANY,
LDAP_XSTRING(wt_id2entry_put)
": open_cursor failed: %s (%d)\n",
wiredtiger_strerror(rc), rc );
goto done;
}
cursor->set_key(cursor, e->e_id);
cursor->set_value(cursor, e->e_ndn, &item);
rc = cursor->insert(cursor);
if ( rc ) {
Debug( LDAP_DEBUG_ANY,
LDAP_XSTRING(wt_id2entry_put)
": insert failed: %s (%d)\n",
"wt_id2entry_put: insert failed: %s (%d)\n",
wiredtiger_strerror(rc), rc );
goto done;
}
done:
ch_free( bv.bv_val );
if(cursor){
cursor->close(cursor);
}
return rc;
}
int wt_id2entry_add(
Operation *op,
WT_SESSION *session,
wt_ctx *wc,
Entry *e )
{
return wt_id2entry_put(op, session, e, "overwrite=false");
WT_SESSION *session = wc->session;
WT_CURSOR *cursor = wc->id2entry_add;
int rc;
if(!cursor){
rc = session->open_cursor(session, WT_TABLE_ID2ENTRY, NULL,
"overwrite=false", &cursor);
if ( rc ) {
Debug( LDAP_DEBUG_ANY,
"wt_id2entry_put: open_cursor failed: %s (%d)\n",
wiredtiger_strerror(rc), rc );
return rc;
}
wc->id2entry_add = cursor;
}
rc = wt_id2entry_put(op, wc, e, cursor);
#ifdef WT_CURSOR_CACHE
if(cursor){
cursor->reset(cursor);
}
#else
if(cursor){
cursor->close(cursor);
wc->id2entry_add = NULL;
}
#endif
return rc;
}
int wt_id2entry_update(
Operation *op,
WT_SESSION *session,
wt_ctx *wc,
Entry *e )
{
return wt_id2entry_put(op, session, e, "overwrite=true");
WT_SESSION *session = wc->session;
WT_CURSOR *cursor = wc->id2entry_update;
int rc;
if(!cursor){
rc = session->open_cursor(session, WT_TABLE_ID2ENTRY, NULL,
"overwrite=true", &cursor);
if ( rc ) {
Debug( LDAP_DEBUG_ANY,
"wt_id2entry_put: open_cursor failed: %s (%d)\n",
wiredtiger_strerror(rc), rc );
return rc;
}
wc->id2entry_update = cursor;
}
rc = wt_id2entry_put(op, wc, e, cursor);
#ifdef WT_CURSOR_CACHE
if(cursor){
cursor->reset(cursor);
}
#else
if(cursor){
cursor->close(cursor);
wc->id2entry_update = NULL;
}
#endif
return rc;
}
int wt_id2entry_delete(
Operation *op,
WT_SESSION *session,
wt_ctx *wc,
Entry *e )
{
int rc;
WT_SESSION *session = wc->session;
WT_CURSOR *cursor = NULL;
rc = session->open_cursor(session, WT_TABLE_ID2ENTRY, NULL,
NULL, &cursor);
if ( rc ) {
Debug( LDAP_DEBUG_ANY,
LDAP_XSTRING(wt_id2entry_delete)
": open_cursor failed: %s (%d)\n",
"wt_id2entry_delete: open_cursor failed: %s (%d)\n",
wiredtiger_strerror(rc), rc );
goto done;
}
@ -104,8 +148,7 @@ int wt_id2entry_delete(
rc = cursor->remove(cursor);
if ( rc ) {
Debug( LDAP_DEBUG_ANY,
LDAP_XSTRING(wt_id2entry_delete)
": remove failed: %s (%d)\n",
"wt_id2entry_delete: remove failed: %s (%d)\n",
wiredtiger_strerror(rc), rc );
goto done;
}
@ -118,24 +161,27 @@ done:
}
int wt_id2entry( BackendDB *be,
WT_SESSION *session,
wt_ctx *wc,
ID id,
Entry **ep ){
int rc;
WT_CURSOR *cursor = NULL;
WT_SESSION *session = wc->session;
WT_CURSOR *cursor = wc->id2entry;
WT_ITEM item;
EntryHeader eh;
int eoff;
Entry *e = NULL;
rc = session->open_cursor(session, WT_TABLE_ID2ENTRY"(entry)", NULL,
NULL, &cursor);
if ( rc ) {
Debug( LDAP_DEBUG_ANY,
LDAP_XSTRING(wt_id2entry)
": open_cursor failed: %s (%d)\n",
wiredtiger_strerror(rc), rc );
goto done;
if(!cursor){
rc = session->open_cursor(session, WT_TABLE_ID2ENTRY"(entry)", NULL,
NULL, &cursor);
if ( rc ) {
Debug( LDAP_DEBUG_ANY,
"wt_id2entry: open_cursor failed: %s (%d)\n",
wiredtiger_strerror(rc), rc );
goto done;
}
wc->id2entry = cursor;
}
cursor->set_key(cursor, id);
@ -156,18 +202,25 @@ int wt_id2entry( BackendDB *be,
rc = entry_decode( &eh, &e );
if ( rc ) {
Debug( LDAP_DEBUG_ANY,
LDAP_XSTRING(wt_id2entry)
": entry decode error: %d\n",
rc );
"wt_id2entry: entry decode error: %s (%d)\n",
wiredtiger_strerror(rc), rc );
goto done;
}
e->e_id = id;
*ep = e;
done:
#ifdef WT_CURSOR_CACHE
if(cursor){
cursor->reset(cursor);
}
#else
if(cursor){
cursor->close(cursor);
wc->id2entry = NULL;
}
#endif
return rc;
}
@ -210,7 +263,6 @@ int wt_entry_release(
Entry *e,
int rw )
{
struct wt_info *wi = (struct wt_info *) op->o_bd->be_private;
return wt_entry_return( e );
}
@ -225,7 +277,70 @@ int wt_entry_get(
int rw,
Entry **ent )
{
return 0;
struct wt_info *wi = (struct wt_info *) op->o_bd->be_private;
wt_ctx *wc;
Entry *e = NULL;
int rc;
const char *at_name = at ? at->ad_cname.bv_val : "(null)";
Debug( LDAP_DEBUG_ARGS,
"wt_entry_get: ndn: \"%s\"\n", ndn->bv_val );
Debug( LDAP_DEBUG_ARGS,
"wt_entry_get: oc: \"%s\", at: \"%s\"\n",
oc ? oc->soc_cname.bv_val : "(null)", at_name );
wc = wt_ctx_get(op, wi);
if( !wc ){
Debug( LDAP_DEBUG_ANY,
"wt_entry_get: wt_ctx_get failed\n" );
return LDAP_OTHER;
}
rc = wt_dn2entry(op->o_bd, wc, ndn, &e);
switch( rc ) {
case 0:
break;
case WT_NOTFOUND:
Debug( LDAP_DEBUG_ACL,
"wt_entry_get: cannot find entry: \"%s\"\n",
ndn->bv_val );
return LDAP_NO_SUCH_OBJECT;
default:
Debug( LDAP_DEBUG_ANY,
"wt_entry_get: wt_dn2entry failed %s rc=%d\n",
wiredtiger_strerror(rc), rc );
rc = LDAP_OTHER;
}
Debug( LDAP_DEBUG_ACL,
"wt_entry_get: found entry: \"%s\"\n", ndn->bv_val );
if ( oc && !is_entry_objectclass( e, oc, 0 )) {
Debug( LDAP_DEBUG_ACL,
"wt_entry_get: failed to find objectClass %s\n",
oc->soc_cname.bv_val );
rc = LDAP_NO_SUCH_ATTRIBUTE;
goto return_results;
}
/* NOTE: attr_find() or attrs_find()? */
if ( at && attr_find( e->e_attrs, at ) == NULL ) {
Debug( LDAP_DEBUG_ACL,
"wt_entry_get: failed to find attribute %s\n",
at->ad_cname.bv_val );
rc = LDAP_NO_SUCH_ATTRIBUTE;
goto return_results;
}
return_results:
if( rc != LDAP_SUCCESS ) {
wt_entry_return( e );
}else{
*ent = e;
}
Debug( LDAP_DEBUG_TRACE, "wt_entry_get: rc=%d\n", rc );
return rc;
}
/*

View file

@ -31,8 +31,7 @@
#define IDL_MIN(x,y) ( (x) < (y) ? (x) : (y) )
#define IDL_CMP(x,y) ( (x) < (y) ? -1 : (x) > (y) )
#if IDL_DEBUG > 0
static void idl_check( ID *ids )
void wt_idl_check( ID *ids )
{
if( WT_IDL_IS_RANGE( ids ) ) {
assert( WT_IDL_RANGE_FIRST(ids) <= WT_IDL_RANGE_LAST(ids) );
@ -44,8 +43,7 @@ static void idl_check( ID *ids )
}
}
#if IDL_DEBUG > 1
static void idl_dump( ID *ids )
void wt_idl_dump( ID *ids )
{
if( WT_IDL_IS_RANGE( ids ) ) {
Debug( LDAP_DEBUG_ANY,
@ -67,10 +65,8 @@ static void idl_dump( ID *ids )
Debug( LDAP_DEBUG_ANY, "\n" );
}
idl_check( ids );
wt_idl_check( ids );
}
#endif /* IDL_DEBUG > 1 */
#endif /* IDL_DEBUG > 0 */
unsigned wt_idl_search( ID *ids, ID id )
{
@ -138,7 +134,7 @@ int wt_idl_insert( ID *ids, ID id )
Debug( LDAP_DEBUG_ANY, "insert: %04lx at %d\n", (long) id, x );
idl_dump( ids );
#elif IDL_DEBUG > 0
idl_check( ids );
wt_idl_check( ids );
#endif
if (WT_IDL_IS_RANGE( ids )) {
@ -183,9 +179,9 @@ int wt_idl_insert( ID *ids, ID id )
}
#if IDL_DEBUG > 1
idl_dump( ids );
wt_idl_dump( ids );
#elif IDL_DEBUG > 0
idl_check( ids );
wt_idl_check( ids );
#endif
return 0;
@ -199,7 +195,7 @@ static int wt_idl_delete( ID *ids, ID id )
Debug( LDAP_DEBUG_ANY, "delete: %04lx at %d\n", (long) id, x );
idl_dump( ids );
#elif IDL_DEBUG > 0
idl_check( ids );
wt_idl_check( ids );
#endif
if (WT_IDL_IS_RANGE( ids )) {
@ -240,9 +236,9 @@ static int wt_idl_delete( ID *ids, ID id )
}
#if IDL_DEBUG > 1
idl_dump( ids );
wt_idl_dump( ids );
#elif IDL_DEBUG > 0
idl_check( ids );
wt_idl_check( ids );
#endif
return 0;

View file

@ -19,7 +19,7 @@
* WiredTiger is a product of MongoDB Inc.
*/
#ifndef _WI_IDL_H_
#ifndef _WT_IDL_H_
#define _WT_IDL_H_
/* IDL sizes - likely should be even bigger

View file

@ -22,6 +22,7 @@
#include "portable.h"
#include <stdio.h>
#include <ac/string.h>
#include "back-wt.h"
#include "slap-config.h"
@ -80,7 +81,6 @@ int wt_index_param(
struct berval *prefixp )
{
AttrInfo *ai;
int rc;
slap_mask_t mask, type = 0;
ai = wt_index_mask( be, desc, prefixp );
@ -148,17 +148,15 @@ static int indexer(
int opid,
slap_mask_t mask )
{
int rc, i;
int rc = LDAP_SUCCESS, i;
struct berval *keys;
WT_CURSOR *cursor = NULL;
WT_SESSION *session = wc->session;
assert( mask != 0 );
cursor = wt_ctx_index_cursor(wc, atname, 1);
cursor = wt_index_open(wc, atname, 1);
if( !cursor ) {
Debug( LDAP_DEBUG_ANY,
LDAP_XSTRING(indexer)
": open index cursor failed: %s\n",
"indexer: open index cursor failed: %s\n",
atname->bv_val );
goto done;
}
@ -236,9 +234,7 @@ static int indexer(
}
done:
if(cursor){
cursor->close(cursor);
}
cursor->close(cursor);
return rc;
}
@ -252,7 +248,7 @@ static int index_at_values(
ID id,
int opid )
{
int rc;
int rc = LDAP_SUCCESS;
slap_mask_t mask = 0;
int ixop = opid;
AttrInfo *ai = NULL;
@ -382,6 +378,42 @@ wt_index_entry( Operation *op, wt_ctx *wc, int opid, Entry *e )
return 0;
}
WT_CURSOR *
wt_index_open(wt_ctx *wc, struct berval *name, int create)
{
WT_CURSOR *cursor = NULL;
WT_SESSION *session = wc->session;
char uri[1024];
int rc;
snprintf(uri, sizeof(uri), "table:%s", name->bv_val);
rc = session->open_cursor(session, uri, NULL, "overwrite=false", &cursor);
if (rc == ENOENT && create) {
rc = session->create(session, uri,
"key_format=uQ,"
"value_format=x,"
"columns=(key, id, none)");
if( rc ) {
Debug( LDAP_DEBUG_ANY,
"wt_index_open: table \"%s\": "
"cannot create index table: %s (%d)\n",
uri, wiredtiger_strerror(rc), rc);
return NULL;
}
rc = session->open_cursor(session, uri, NULL,
"overwrite=false", &cursor);
}
if ( rc ) {
Debug( LDAP_DEBUG_ANY,
"wt_index_open: table \"%s\": "
": open cursor failed: %s (%d)\n",
uri, wiredtiger_strerror(rc), rc);
return NULL;
}
return cursor;
}
/*
* Local variables:
* indent-tabs-mode: t

View file

@ -31,17 +31,21 @@ wt_db_init( BackendDB *be, ConfigReply *cr )
{
struct wt_info *wi;
Debug( LDAP_DEBUG_TRACE,
LDAP_XSTRING(wt_db_init) ": Initializing wt backend\n" );
Debug( LDAP_DEBUG_TRACE, "wt_db_init: Initializing wt backend\n" );
/* allocate backend-database-specific stuff */
wi = ch_calloc( 1, sizeof(struct wt_info) );
wi->wi_dbenv_home = ch_strdup( SLAPD_DEFAULT_DB_DIR );
wi->wi_dbenv_config = ch_strdup("create");
wi = ch_calloc( 1, sizeof(struct wt_info) );
wi->wi_home = ch_strdup( SLAPD_DEFAULT_DB_DIR );
wi->wi_config = ch_calloc( 1, WT_CONFIG_MAX + 1);
if ( slapMode & SLAP_TOOL_READONLY ) {
strcpy(wi->wi_config, "readonly");
} else {
strcpy(wi->wi_config, "create");
}
wi->wi_lastid = 0;
wi->wi_search_stack_depth = DEFAULT_SEARCH_STACK_DEPTH;
wi->wi_search_stack = NULL;
wi->wi_flags = WT_USE_IDLCACHE;
be->be_private = wi;
be->be_cf_ocs = be->bd_info->bi_cf_ocs;
@ -55,51 +59,65 @@ wt_db_open( BackendDB *be, ConfigReply *cr )
struct wt_info *wi = (struct wt_info *) be->be_private;
int rc;
struct stat st;
WT_CONNECTION *conn;
WT_SESSION *session;
WT_SESSION *session = NULL;
WT_SESSION *cache_session = NULL;
if ( be->be_suffix == NULL ) {
Debug( LDAP_DEBUG_ANY,
LDAP_XSTRING(wt_db_open) ": need suffix.\n" );
Debug( LDAP_DEBUG_ANY, "wt_db_open: need suffix.\n" );
return -1;
}
Debug( LDAP_DEBUG_ARGS,
LDAP_XSTRING(wt_db_open) ": \"%s\"\n",
be->be_suffix[0].bv_val );
"wt_db_open: \"%s\", home=%s, config=%s\n",
be->be_suffix[0].bv_val, wi->wi_home, wi->wi_config );
/* Check existence of home. Any error means trouble */
rc = stat( wi->wi_dbenv_home, &st );
rc = stat( wi->wi_home, &st );
if( rc ) {
int saved_errno = errno;
Debug( LDAP_DEBUG_ANY,
LDAP_XSTRING(wt_db_open) ": database \"%s\": "
"wt_db_open: database \"%s\": "
"cannot access database directory \"%s\" (%d).\n",
be->be_suffix[0].bv_val, wi->wi_dbenv_home, saved_errno );
be->be_suffix[0].bv_val, wi->wi_home, saved_errno );
return -1;
}
/* Open and create database */
rc = wiredtiger_open(wi->wi_dbenv_home, NULL,
wi->wi_dbenv_config, &conn);
rc = wiredtiger_open(wi->wi_home, NULL,
wi->wi_config, &wi->wi_conn);
if( rc ) {
int saved_errno = errno;
Debug( LDAP_DEBUG_ANY,
LDAP_XSTRING(wt_db_open) ": database \"%s\": "
"wt_db_open: database \"%s\": "
"cannot open database \"%s\" (%d).\n",
be->be_suffix[0].bv_val, wi->wi_dbenv_home, saved_errno );
be->be_suffix[0].bv_val, wi->wi_home, saved_errno );
return -1;
}
rc = conn->open_session(conn, NULL, NULL, &session);
rc = wi->wi_conn->open_session(wi->wi_conn, NULL, NULL, &session);
if( rc ) {
Debug( LDAP_DEBUG_ANY,
LDAP_XSTRING(wt_db_open) ": database \"%s\": "
"wt_db_open: database \"%s\": "
"cannot open session: \"%s\"\n",
be->be_suffix[0].bv_val, wiredtiger_strerror(rc) );
return -1;
}
if ( slapMode & SLAP_TOOL_READONLY ) {
goto readonly;
}
/* checking for obsolete table */
rc = session->verify(session, WT_INDEX_REVDN, NULL);
if ( !rc ) {
Debug( LDAP_DEBUG_ANY,
"wt_db_open: database \"%s\": "
"incompatible wiredtiger table, please restore from LDIF.\n",
be->be_suffix[0].bv_val );
return -1;
}
/* create tables and indexes */
rc = session->create(session,
WT_TABLE_ID2ENTRY,
"key_format=Q,"
@ -107,7 +125,7 @@ wt_db_open( BackendDB *be, ConfigReply *cr )
"columns=(id,dn,entry)");
if( rc ) {
Debug( LDAP_DEBUG_ANY,
LDAP_XSTRING(wt_db_open) ": database \"%s\": "
"wt_db_open: database \"%s\": "
"cannot create entry table: \"%s\"\n",
be->be_suffix[0].bv_val, wiredtiger_strerror(rc) );
return -1;
@ -116,11 +134,11 @@ wt_db_open( BackendDB *be, ConfigReply *cr )
rc = session->create(session,
WT_TABLE_DN2ID,
"key_format=S,"
"value_format=QQS,"
"columns=(ndn,id,pid,revdn)");
"value_format=SQQ,"
"columns=(revdn,ndn,id,pid)");
if( rc ) {
Debug( LDAP_DEBUG_ANY,
LDAP_XSTRING(wt_db_open) ": database \"%s\": "
"wt_db_open: database \"%s\": "
"cannot create entry table: \"%s\"\n",
be->be_suffix[0].bv_val, wiredtiger_strerror(rc) );
return -1;
@ -130,7 +148,7 @@ wt_db_open( BackendDB *be, ConfigReply *cr )
rc = session->create(session, WT_INDEX_DN, "columns=(dn)");
if( rc ) {
Debug( LDAP_DEBUG_ANY,
LDAP_XSTRING(wt_db_open) ": database \"%s\": "
"wt_db_open: database \"%s\": "
"cannot create dn index: \"%s\"\n",
be->be_suffix[0].bv_val, wiredtiger_strerror(rc) );
return -1;
@ -139,36 +157,72 @@ wt_db_open( BackendDB *be, ConfigReply *cr )
rc = session->create(session, WT_INDEX_PID, "columns=(pid)");
if( rc ) {
Debug( LDAP_DEBUG_ANY,
LDAP_XSTRING(wt_db_open) ": database \"%s\": "
"wt_db_open: database \"%s\": "
"cannot create pid index: \"%s\"\n",
be->be_suffix[0].bv_val, wiredtiger_strerror(rc) );
return -1;
}
rc = session->create(session, WT_INDEX_REVDN, "columns=(revdn)");
rc = session->create(session, WT_INDEX_NDN, "columns=(ndn)");
if( rc ) {
Debug( LDAP_DEBUG_ANY,
LDAP_XSTRING(wt_db_open) ": database \"%s\": "
"cannot create revdn index: \"%s\"\n",
"wt_db_open: database \"%s\": "
"cannot create ndn index: \"%s\"\n",
be->be_suffix[0].bv_val, wiredtiger_strerror(rc) );
return -1;
}
/* open in-memory database for idlcache */
rc = wiredtiger_open(be->be_suffix[0].bv_val, NULL,
"in_memory=true", &wi->wi_cache);
if( rc ) {
Debug( LDAP_DEBUG_ANY,
"wt_db_open: database \"%s\": "
"cannot open database for cache (%s).\n",
be->be_suffix[0].bv_val, wiredtiger_strerror(rc) );
return -1;
}
rc = wi->wi_cache->open_session(wi->wi_cache, NULL, NULL, &cache_session);
if( rc ) {
Debug( LDAP_DEBUG_ANY,
"wt_db_open: database \"%s\": "
"cannot open session for cache: \"%s\"\n",
be->be_suffix[0].bv_val, wiredtiger_strerror(rc) );
return -1;
}
rc = cache_session->create(cache_session,
WT_TABLE_IDLCACHE,
"key_format=Sb,"
"value_format=u,"
"columns=(ndn,scope,idl)");
if( rc ) {
Debug( LDAP_DEBUG_ANY,
"wt_db_open: database \"%s\": "
"cannot create idlcache table: \"%s\"\n",
be->be_suffix[0].bv_val, wiredtiger_strerror(rc) );
return -1;
}
readonly:
rc = wt_last_id( be, session, &wi->wi_lastid);
if (rc) {
snprintf( cr->msg, sizeof(cr->msg), "database \"%s\": "
"last_id() failed: %s(%d).",
be->be_suffix[0].bv_val, wiredtiger_strerror(rc), rc );
Debug( LDAP_DEBUG_ANY,
LDAP_XSTRING(wt_db_open) ": %s\n",
cr->msg );
Debug( LDAP_DEBUG_ANY, "wt_db_open: %s\n", cr->msg );
return rc;
}
session->close(session, NULL);
wi->wi_conn = conn;
wi->wi_flags |= WT_IS_OPEN;
if (session) {
session->close(session, NULL);
}
if (cache_session) {
cache_session->close(cache_session, NULL);
}
wi->wi_flags |= WT_IS_OPEN;
return LDAP_SUCCESS;
}
@ -178,13 +232,15 @@ wt_db_close( BackendDB *be, ConfigReply *cr )
struct wt_info *wi = (struct wt_info *) be->be_private;
int rc;
if ( !wi->wi_conn ) {
return -1;
}
rc = wi->wi_conn->close(wi->wi_conn, NULL);
if( rc ) {
int saved_errno = errno;
Debug( LDAP_DEBUG_ANY,
LDAP_XSTRING(wt_db_close)
": cannot close database (%d).\n",
saved_errno );
"wt_db_close: cannot close database (%d).\n", saved_errno );
return -1;
}
@ -198,13 +254,14 @@ wt_db_destroy( Backend *be, ConfigReply *cr )
{
struct wt_info *wi = (struct wt_info *) be->be_private;
if( wi->wi_dbenv_home ) {
ch_free( wi->wi_dbenv_home );
wi->wi_dbenv_home = NULL;
if( wi->wi_home ) {
ch_free( wi->wi_home );
wi->wi_home = NULL;
}
if( wi->wi_dbenv_config ) {
ch_free( wi->wi_dbenv_config );
wi->wi_dbenv_config = NULL;
if( wi->wi_config ) {
ch_free( wi->wi_config );
wi->wi_config = NULL;
}
wt_attr_index_destroy( wi );
@ -217,7 +274,7 @@ wt_db_destroy( Backend *be, ConfigReply *cr )
int
wt_back_initialize( BackendInfo *bi )
{
static char *controls[] = {
static const char *controls[] = {
LDAP_CONTROL_ASSERT,
LDAP_CONTROL_MANAGEDSAIT,
LDAP_CONTROL_NOOP,
@ -226,13 +283,15 @@ wt_back_initialize( BackendInfo *bi )
LDAP_CONTROL_POST_READ,
LDAP_CONTROL_SUBENTRIES,
LDAP_CONTROL_X_PERMISSIVE_MODIFY,
#ifdef LDAP_X_TXN
LDAP_CONTROL_X_TXN_SPEC,
#endif
NULL
};
/* initialize the database system */
Debug( LDAP_DEBUG_TRACE,
LDAP_XSTRING(wt_back_initialize)
": initialize WiredTiger backend\n" );
"wt_back_initialize: initialize WiredTiger backend\n" );
bi->bi_flags |=
SLAP_BFLAG_INCREMENT |
@ -240,10 +299,11 @@ wt_back_initialize( BackendInfo *bi )
SLAP_BFLAG_ALIASES |
SLAP_BFLAG_REFERRALS;
bi->bi_controls = controls;
/* version check */
bi->bi_controls = (char **)controls;
/* version check */
Debug( LDAP_DEBUG_TRACE,
LDAP_XSTRING(wt_back_initialize) ": %s\n",
"wt_back_initialize: %s\n",
wiredtiger_version(NULL, NULL, NULL) );
bi->bi_open = 0;
@ -263,15 +323,19 @@ wt_back_initialize( BackendInfo *bi )
bi->bi_op_search = wt_search;
bi->bi_op_compare = wt_compare;
bi->bi_op_modify = wt_modify;
bi->bi_op_modrdn = 0;
bi->bi_op_modrdn = wt_modrdn;
bi->bi_op_delete = wt_delete;
bi->bi_op_abandon = 0;
bi->bi_extended = 0;
bi->bi_extended = wt_extended;
#ifdef LDAP_X_TXN
bi->bi_op_txn = 0;
#endif
bi->bi_chk_referrals = 0;
bi->bi_operational = wt_operational;
bi->bi_has_subordinates = wt_hasSubordinates;
bi->bi_entry_release_rw = wt_entry_release;
bi->bi_entry_get_rw = wt_entry_get;
@ -283,6 +347,13 @@ wt_back_initialize( BackendInfo *bi )
bi->bi_tool_entry_get = wt_tool_entry_get;
bi->bi_tool_entry_put = wt_tool_entry_put;
bi->bi_tool_entry_reindex = wt_tool_entry_reindex;
bi->bi_tool_sync = 0;
bi->bi_tool_dn2id_get = wt_tool_dn2id_get;
bi->bi_tool_entry_modify = wt_tool_entry_modify;
#if LDAP_VENDOR_VERSION_MINOR == X || LDAP_VENDOR_VERSION_MINOR >= 5
bi->bi_tool_entry_delete = wt_tool_entry_delete;
#endif
bi->bi_connection_init = 0;
bi->bi_connection_destroy = 0;

View file

@ -32,7 +32,7 @@ int
wt_key_read(
Backend *be,
WT_CURSOR *cursor,
struct berval *k,
struct berval *bkey,
ID *ids,
WT_CURSOR **saved_cursor,
int get_flag
@ -43,33 +43,42 @@ wt_key_read(
int exact;
WT_ITEM key2;
ID id;
int comp;
long scanned = 0;
Debug( LDAP_DEBUG_TRACE, "=> key_read\n" );
WT_IDL_ZERO(ids);
bv2ITEM(k, &key);
bv2ITEM(bkey, &key);
cursor->set_key(cursor, &key, 0);
rc = cursor->search_near(cursor, &exact);
if( rc ){
switch( rc ){
case 0:
break;
case WT_NOTFOUND:
rc = LDAP_SUCCESS;
goto done;
default:
Debug( LDAP_DEBUG_ANY,
LDAP_XSTRING(wt_key_read)
": search_near failed: %s (%d)\n",
wiredtiger_strerror(rc), rc );
"wt_key_read: search_near failed: %s (%d)\n",
wiredtiger_strerror(rc), rc);
goto done;
}
do {
scanned++;
rc = cursor->get_key(cursor, &key2, &id);
if( rc ){
Debug( LDAP_DEBUG_ANY,
LDAP_XSTRING(wt_key_read)
": get_key failed: %s (%d)\n",
"wt_key_read: get_key failed: %s (%d)\n",
wiredtiger_strerror(rc), rc );
break;
}
if (key.size != key2.size || memcmp(key.data, key2.data, key.size)) {
comp = 0;
if (key.size != key2.size ||
(comp = memcmp(key2.data, key.data, key.size))) {
if(comp > 0){
break;
}
if(exact < 0){
rc = cursor->next(cursor);
if (rc) {
@ -85,17 +94,17 @@ wt_key_read(
rc = cursor->next(cursor);
} while(rc == 0);
if (rc == WT_NOTFOUND ) {
if ( rc == WT_NOTFOUND && exact == 0 ) {
rc = LDAP_SUCCESS;
}
done:
if( rc != LDAP_SUCCESS ) {
Debug( LDAP_DEBUG_TRACE, "<= wt_key_read: failed (%d)\n",
rc );
Debug( LDAP_DEBUG_TRACE, "<= wt_key_read: failed (%d) %ld scanned\n",
rc, scanned );
} else {
Debug( LDAP_DEBUG_TRACE, "<= wt_key_read %ld candidates\n",
(long) WT_IDL_N(ids) );
Debug( LDAP_DEBUG_TRACE, "<= wt_key_read %ld candidates %ld scanned\n",
(long) WT_IDL_N(ids), scanned );
}
return rc;
@ -131,10 +140,11 @@ wt_key_change(
if ( rc == WT_NOTFOUND ) rc = 0;
}
if( rc ) {
Debug( LDAP_DEBUG_ANY,
LDAP_XSTRING(wt_key_change)
": error: %s (%d)\n",
wiredtiger_strerror(rc), rc );
if ( rc != WT_ROLLBACK ) {
Debug( LDAP_DEBUG_ANY,
"wt_key_change: error: %s (%d)\n",
wiredtiger_strerror(rc), rc);
}
return rc;
}

View file

@ -10,7 +10,7 @@
* Public License.
*
* A copy of this license is available in the file LICENSE in the
* top-level directory of the distribution or, alternatively, at
B * top-level directory of the distribution or, alternatively, at
* <http://www.OpenLDAP.org/license.html>.
*/
/* ACKNOWLEDGEMENTS:
@ -21,6 +21,7 @@
#include "portable.h"
#include <stdio.h>
#include <ac/string.h>
#include "back-wt.h"
#include "slap-config.h"
@ -150,7 +151,7 @@ int wt_modify_internal(
break;
}
Debug(LDAP_DEBUG_ARGS,
Debug( LDAP_DEBUG_ARGS,
"wt_modify_internal: delete %s\n",
mod->sm_desc->ad_cname.bv_val );
err = modify_delete_values( e, mod, get_permissiveModify(op),
@ -164,7 +165,7 @@ int wt_modify_internal(
break;
case LDAP_MOD_REPLACE:
Debug(LDAP_DEBUG_ARGS,
Debug( LDAP_DEBUG_ARGS,
"wt_modify_internal: replace %s\n",
mod->sm_desc->ad_cname.bv_val );
err = modify_replace_values( e, mod, get_permissiveModify(op),
@ -178,22 +179,21 @@ int wt_modify_internal(
break;
case LDAP_MOD_INCREMENT:
Debug(LDAP_DEBUG_ARGS,
Debug( LDAP_DEBUG_ARGS,
"wt_modify_internal: increment %s\n",
mod->sm_desc->ad_cname.bv_val );
err = modify_increment_values( e, mod, get_permissiveModify(op),
text, textbuf, textlen );
if( err != LDAP_SUCCESS ) {
Debug(LDAP_DEBUG_ARGS,
"wt_modify_internal: %d %s\n",
err, *text );
Debug( LDAP_DEBUG_ARGS,
"wt_modify_internal: %d %s\n", err, *text );
} else {
got_delete = 1;
}
break;
case SLAP_MOD_SOFTADD:
Debug(LDAP_DEBUG_ARGS,
Debug( LDAP_DEBUG_ARGS,
"wt_modify_internal: softadd %s\n",
mod->sm_desc->ad_cname.bv_val );
/* Avoid problems in index_add_mods()
@ -217,7 +217,7 @@ int wt_modify_internal(
break;
case SLAP_MOD_SOFTDEL:
Debug(LDAP_DEBUG_ARGS,
Debug( LDAP_DEBUG_ARGS,
"wt_modify_internal: softdel %s\n",
mod->sm_desc->ad_cname.bv_val );
/* Avoid problems in index_delete_mods()
@ -314,8 +314,7 @@ int wt_modify_internal(
if ( rc != LDAP_SUCCESS ) {
Debug( LDAP_DEBUG_ANY,
"entry failed schema check: %s\n",
*text );
"entry failed schema check: %s\n", *text );
}
/* if NOOP then silently revert to saved attrs */
@ -447,7 +446,7 @@ wt_modify( Operation *op, SlapReply *rs )
{
struct wt_info *wi = (struct wt_info *) op->o_bd->be_private;
wt_ctx *wc = NULL;
Entry *e = NULL;
Entry *e = NULL;
int manageDSAit = get_manageDSAit( op );
char textbuf[SLAP_TEXT_BUFLEN];
size_t textlen = sizeof textbuf;
@ -460,19 +459,18 @@ wt_modify( Operation *op, SlapReply *rs )
int rc;
Debug( LDAP_DEBUG_ARGS, LDAP_XSTRING(wt_modify) ": %s\n",
op->o_req_dn.bv_val );
Debug( LDAP_DEBUG_ARGS, "wt_modify: %s\n", op->o_req_dn.bv_val );
#ifdef LDAP_X_TXN
if( op->o_txnSpec && txn_preop( op, rs ))
return rs->sr_err;
#endif
ctrls[num_ctrls] = NULL;
wc = wt_ctx_get(op, wi);
if( !wc ){
Debug( LDAP_DEBUG_ANY,
LDAP_XSTRING(wt_add)
": wt_ctx_get failed\n" );
Debug( LDAP_DEBUG_ANY, "wt_modify: wt_ctx_get failed\n" );
rs->sr_err = LDAP_OTHER;
rs->sr_text = "internal error";
send_ldap_result( op, rs );
@ -487,35 +485,75 @@ wt_modify( Operation *op, SlapReply *rs )
slap_mods_opattrs( op, &op->orm_modlist, 1 );
}
retry:
/* begin transaction */
wc->is_begin_transaction = 0;
rc = wc->session->begin_transaction(wc->session, "isolation=snapshot");
if( rc ) {
Debug( LDAP_DEBUG_TRACE,
"wt_modify: begin_transaction failed: %s (%d)\n",
wiredtiger_strerror(rc), rc );
rs->sr_err = LDAP_OTHER;
rs->sr_text = "begin_transaction failed";
goto return_results;
}
wc->is_begin_transaction = 1;
Debug( LDAP_DEBUG_TRACE, "wt_modify: session id: %p\n", wc->session );
/* get entry */
rc = wt_dn2entry(op->o_bd, wc, &op->o_req_ndn, &e);
switch( rc ) {
case 0:
break;
case WT_NOTFOUND:
Debug( LDAP_DEBUG_ARGS,
"<== " LDAP_XSTRING(wt_delete)
": no such object %s\n",
op->o_req_dn.bv_val );
/* TODO: lookup referrals */
rs->sr_err = LDAP_NO_SUCH_OBJECT;
goto return_results;
break;
default:
Debug( LDAP_DEBUG_ANY,
LDAP_XSTRING(wt_modify)
": wt_dn2entry failed (%d)\n",
rc );
"<== wt_modify: wt_dn2entry failed (%d)\n", rc );
rs->sr_err = LDAP_OTHER;
rs->sr_text = "internal error";
goto return_results;
}
if ( rc == WT_NOTFOUND ||
( !manageDSAit && e && is_entry_glue( e ))) {
if ( !e ) {
rc = wt_dn2aentry(op->o_bd, wc, &op->o_req_ndn, &e);
switch( rc ) {
case 0:
break;
case WT_NOTFOUND:
rs->sr_err = LDAP_NO_SUCH_OBJECT;
goto return_results;
default:
Debug( LDAP_DEBUG_ANY, "wt_modify: wt_dna2entry failed (%d)\n", rc );
rs->sr_err = LDAP_OTHER;
rs->sr_text = "internal error";
goto return_results;
}
}
rs->sr_matched = ch_strdup( e->e_dn );
if ( is_entry_referral( e ) ) {
BerVarray ref = get_entry_referrals( op, e );
rs->sr_ref = referral_rewrite( ref, &e->e_name,
&op->o_req_dn, LDAP_SCOPE_DEFAULT );
ber_bvarray_free( ref );
} else {
rs->sr_ref = NULL;
}
rs->sr_flags = REP_MATCHED_MUSTBEFREED | REP_REF_MUSTBEFREED;
rs->sr_err = LDAP_REFERRAL;
send_ldap_result( op, rs );
goto done;
}
if ( !manageDSAit && is_entry_referral( e ) ) {
/* entry is a referral, don't allow modify */
rs->sr_ref = get_entry_referrals( op, e );
Debug( LDAP_DEBUG_TRACE,
LDAP_XSTRING(wt_modify) ": entry is referral\n" );
Debug( LDAP_DEBUG_TRACE, "wt_modify: entry is referral\n" );
rs->sr_err = LDAP_REFERRAL;
rs->sr_matched = e->e_name.bv_val;
@ -541,8 +579,7 @@ wt_modify( Operation *op, SlapReply *rs )
&slap_pre_read_bv, preread_ctrl ) )
{
Debug( LDAP_DEBUG_TRACE,
"<=- " LDAP_XSTRING(wt_modify) ": pre-read "
"failed!\n" );
"<=- wt_modify: pre-read failed!\n" );
if ( op->o_preread & SLAP_CONTROL_CRITICAL ) {
/* FIXME: is it correct to abort
* operation if control fails? */
@ -551,72 +588,46 @@ wt_modify( Operation *op, SlapReply *rs )
}
}
/* begin transaction */
rc = wc->session->begin_transaction(wc->session, NULL);
if( rc ) {
Debug( LDAP_DEBUG_TRACE,
LDAP_XSTRING(wt_add) ": begin_transaction failed: %s (%d)\n",
wiredtiger_strerror(rc), rc );
rs->sr_err = LDAP_OTHER;
rs->sr_text = "begin_transaction failed";
goto return_results;
}
Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(wt_modify) ": session id: %p\n",
wc->session );
/* Modify the entry */
dummy = *e;
rs->sr_err = wt_modify_internal( op, wc, op->orm_modlist,
&dummy, &rs->sr_text, textbuf, textlen );
if( rs->sr_err != LDAP_SUCCESS ) {
Debug( LDAP_DEBUG_TRACE,
LDAP_XSTRING(wt_modify) ": modify failed (%d)\n",
rs->sr_err );
switch ( rs->sr_err ) {
case LDAP_SUCCESS:
break;
case WT_ROLLBACK:
Debug (LDAP_DEBUG_TRACE, "wt_modify: rollback wt_modify_internal failed.\n" );
wc->session->rollback_transaction(wc->session, NULL);
goto retry;
default:
Debug( LDAP_DEBUG_ANY, "wt_modify: modify failed (%d)\n", rs->sr_err );
/* Only free attrs if they were dup'd. */
if ( dummy.e_attrs == e->e_attrs ) dummy.e_attrs = NULL;
goto return_results;
}
/* change the entry itself */
rs->sr_err = wt_id2entry_update( op, wc->session, &dummy );
if ( rs->sr_err != 0 ) {
Debug( LDAP_DEBUG_TRACE,
LDAP_XSTRING(wt_modify) ": id2entry update failed " "(%d)\n",
rs->sr_err );
if ( rs->sr_err == LDAP_ADMINLIMIT_EXCEEDED ) {
rs->sr_text = "entry too big";
} else {
rs->sr_err = LDAP_OTHER;
rs->sr_text = "entry update failed";
}
goto return_results;
}
if( op->o_noop ) {
rs->sr_err = wt_id2entry_update( op, wc, &dummy );
switch ( rs->sr_err ) {
case 0:
break;
case WT_ROLLBACK:
Debug (LDAP_DEBUG_TRACE, "wt_modify: rollback wt_id2entry_update failed.\n");
wc->session->rollback_transaction(wc->session, NULL);
rs->sr_err = LDAP_X_NO_OPERATION;
goto retry;
case LDAP_ADMINLIMIT_EXCEEDED:
Debug( LDAP_DEBUG_ANY, "wt_modify: id2entry update failed (%d)\n",
rs->sr_err);
rs->sr_text = "entry too big";
goto return_results;
}
/* Only free attrs if they were dup'd. */
if ( dummy.e_attrs == e->e_attrs ) dummy.e_attrs = NULL;
rc = wc->session->commit_transaction(wc->session, NULL);
if( rc ) {
Debug( LDAP_DEBUG_TRACE,
"<== " LDAP_XSTRING(wt_modify)
": commit failed: %s (%d)\n",
wiredtiger_strerror(rc), rc );
default:
Debug( LDAP_DEBUG_ANY, "wt_modify: id2entry update failed (%d)\n",
rs->sr_err);
rs->sr_err = LDAP_OTHER;
rs->sr_text = "commit failed";
rs->sr_text = "entry update failed";
goto return_results;
}
Debug( LDAP_DEBUG_TRACE,
LDAP_XSTRING(wt_modify) ": updated%s id=%08lx dn=\"%s\"\n",
op->o_noop ? " (no-op)" : "",
dummy.e_id, op->o_req_dn.bv_val );
if( op->o_postread ) {
if( postread_ctrl == NULL ) {
postread_ctrl = &ctrls[num_ctrls++];
@ -626,8 +637,7 @@ wt_modify( Operation *op, SlapReply *rs )
&slap_post_read_bv, postread_ctrl ) )
{
Debug( LDAP_DEBUG_TRACE,
"<=- " LDAP_XSTRING(wt_modify)
": post-read failed!\n" );
"<== wt_modify: post-read failed!\n");
if ( op->o_postread & SLAP_CONTROL_CRITICAL ) {
/* FIXME: is it correct to abort
* operation if control fails? */
@ -635,10 +645,34 @@ wt_modify( Operation *op, SlapReply *rs )
}
}
}
if( num_ctrls ) rs->sr_ctrls = ctrls;
if( op->o_noop ) {
rs->sr_err = LDAP_X_NO_OPERATION;
goto return_results;
}
/* Only free attrs if they were dup'd. */
if ( dummy.e_attrs == e->e_attrs ) dummy.e_attrs = NULL;
rc = wc->session->commit_transaction(wc->session, NULL);
wc->is_begin_transaction = 0;
if( rc ) {
Debug( LDAP_DEBUG_TRACE,
"<== wt_modify: commit failed: %s (%d)\n",
wiredtiger_strerror(rc), rc );
rs->sr_err = LDAP_OTHER;
rs->sr_text = "commit failed";
goto return_results;
}
Debug( LDAP_DEBUG_TRACE,
"wt_modify: updated%s id=%08lx dn=\"%s\"\n",
op->o_noop ? " (no-op)" : "",
dummy.e_id, op->o_req_dn.bv_val );
rs->sr_err = LDAP_SUCCESS;
rs->sr_text = NULL;
if( num_ctrls ) rs->sr_ctrls = ctrls;
return_results:
if( dummy.e_attrs ) {
@ -649,6 +683,12 @@ return_results:
done:
slap_graduate_commit_csn( op );
if( wc && wc->is_begin_transaction ){
Debug( LDAP_DEBUG_TRACE, "wt_modify: rollback transaction\n" );
wc->session->rollback_transaction(wc->session, NULL);
wc->is_begin_transaction = 0;
}
if( e != NULL ) {
wt_entry_return( e );
}
@ -662,8 +702,6 @@ done:
slap_sl_free( *postread_ctrl, op->o_tmpmemctx );
}
rs->sr_text = NULL;
return rs->sr_err;
}

View file

@ -0,0 +1,552 @@
/* OpenLDAP WiredTiger backend */
/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
*
* Copyright 2002-2015 The OpenLDAP Foundation.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted only as authorized by the OpenLDAP
* Public License.
*
* A copy of this license is available in the file LICENSE in the
* top-level directory of the distribution or, alternatively, at
* <http://www.OpenLDAP.org/license.html>.
*/
/* ACKNOWLEDGEMENTS:
* This work was developed by HAMANO Tsukasa <hamano@osstech.co.jp>
* based on back-bdb for inclusion in OpenLDAP Software.
* WiredTiger is a product of MongoDB Inc.
*/
#include "portable.h"
#include <stdio.h>
#include "back-wt.h"
#include "slap-config.h"
int
wt_modrdn( Operation *op, SlapReply *rs )
{
struct wt_info *wi = (struct wt_info *) op->o_bd->be_private;
AttributeDescription *children = slap_schema.si_ad_children;
AttributeDescription *entry = slap_schema.si_ad_entry;
wt_ctx *wc = NULL;
Entry *e = NULL;
Entry *p = NULL;
Entry *ne = NULL;
Entry dummy = {0};
struct berval p_dn, p_ndn;
struct berval new_dn = {0, NULL}, new_ndn = {0, NULL};
Entry *np = NULL; /* newSuperior Entry */
struct berval *np_dn = NULL; /* newSuperior dn */
struct berval *np_ndn = NULL; /* newSuperior ndn */
struct berval *new_parent_dn = NULL; /* np_dn, p_dn, or NULL */
int manageDSAit = get_manageDSAit( op );
char textbuf[SLAP_TEXT_BUFLEN];
size_t textlen = sizeof textbuf;
LDAPControl **preread_ctrl = NULL;
LDAPControl **postread_ctrl = NULL;
LDAPControl *ctrls[SLAP_MAX_RESPONSE_CONTROLS];
int num_ctrls = 0;
int rc;
int parent_is_glue = 0;
int parent_is_leaf = 0;
Debug( LDAP_DEBUG_TRACE, "==> wt_modrdn(%s -> newrdn=%s - newsup=%s)\n",
op->o_req_dn.bv_val,
op->oq_modrdn.rs_newrdn.bv_val,
op->oq_modrdn.rs_newSup?op->oq_modrdn.rs_newSup->bv_val:"NULL" );
ctrls[num_ctrls] = NULL;
slap_mods_opattrs( op, &op->orr_modlist, 1 );
wc = wt_ctx_get(op, wi);
if( !wc ){
Debug( LDAP_DEBUG_ANY, "wt_modrdn: wt_ctx_get failed\n");
rs->sr_err = LDAP_OTHER;
rs->sr_text = "internal error";
send_ldap_result( op, rs );
return rs->sr_err;
}
/* get parent entry */
if ( be_issuffix( op->o_bd, &op->o_req_ndn ) ) {
rs->sr_err = LDAP_NAMING_VIOLATION;
rs->sr_text = "cannot rename suffix entry";
goto return_results;
} else {
dnParent( &op->o_req_ndn, &p_ndn );
}
rc = wt_dn2entry(op->o_bd, wc, &p_ndn, &p);
switch( rc ) {
case 0:
break;
case WT_NOTFOUND:
Debug( LDAP_DEBUG_ARGS,
"<== wt_modrdn: parent does not exist %s\n", p_ndn.bv_val);
rs->sr_err = LDAP_NO_SUCH_OBJECT;
goto return_results;
default:
Debug( LDAP_DEBUG_ANY,
"<== wt_modrdn: wt_dn2entry failed (%d)\n", rc );
rs->sr_err = LDAP_OTHER;
rs->sr_text = "internal error";
goto return_results;
}
/* check parent for "children" acl */
rc = access_allowed( op, p, children, NULL,
op->oq_modrdn.rs_newSup == NULL ?
ACL_WRITE : ACL_WDEL, NULL );
if ( !rc ) {
rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
Debug( LDAP_DEBUG_TRACE,
"wt_modrdn: no access to parent\n");
rs->sr_text = "no write access to old parent's children";
goto return_results;
}
Debug( LDAP_DEBUG_TRACE,
"wt_modrdn: wr to children of entry %s OK\n", p_ndn.bv_val );
if ( p_ndn.bv_val == slap_empty_bv.bv_val ) {
p_dn = slap_empty_bv;
} else {
dnParent( &op->o_req_dn, &p_dn );
}
Debug( LDAP_DEBUG_TRACE,
"wt_modrdn: parent dn=%s\n", p_dn.bv_val );
/* get entry */
rc = wt_dn2entry(op->o_bd, wc, &op->o_req_ndn, &e);
switch( rc ) {
case 0:
break;
case WT_NOTFOUND:
break;
default:
Debug( LDAP_DEBUG_ANY,
"<== wt_modrdn: wt_dn2entry failed (%d)\n", rc );
rs->sr_err = LDAP_OTHER;
rs->sr_text = "internal error";
goto return_results;
}
if ( rc == WT_NOTFOUND ||
( !manageDSAit && e && is_entry_glue( e ) )) {
if ( !e ) {
Debug( LDAP_DEBUG_ARGS,
"<== wt_modrdn: no such object %s\n", op->o_req_dn.bv_val);
rc = wt_dn2aentry(op->o_bd, wc, &op->o_req_ndn, &e);
switch( rc ) {
case 0:
break;
case WT_NOTFOUND:
rs->sr_err = LDAP_NO_SUCH_OBJECT;
goto return_results;
default:
Debug( LDAP_DEBUG_ANY, "wt_modrdn: wt_dn2aentry failed (%d)\n", rc );
rs->sr_err = LDAP_OTHER;
rs->sr_text = "internal error";
goto return_results;
}
}
rs->sr_matched = ch_strdup( e->e_dn );
if ( is_entry_referral( e ) ) {
BerVarray ref = get_entry_referrals( op, e );
rs->sr_ref = referral_rewrite( ref, &e->e_name,
&op->o_req_dn, LDAP_SCOPE_DEFAULT );
ber_bvarray_free( ref );
} else {
rs->sr_ref = NULL;
}
rs->sr_flags = REP_MATCHED_MUSTBEFREED | REP_REF_MUSTBEFREED;
rs->sr_err = LDAP_REFERRAL;
send_ldap_result( op, rs );
goto done;
}
if ( get_assert( op ) &&
( test_filter( op, e, get_assertion( op )) != LDAP_COMPARE_TRUE ))
{
rs->sr_err = LDAP_ASSERTION_FAILED;
goto return_results;
}
/* check write on old entry */
rc = access_allowed( op, e, entry, NULL, ACL_WRITE, NULL );
if ( !rc ) {
Debug( LDAP_DEBUG_TRACE, "wt_modrdn: no access to entry\n");
rs->sr_text = "no write access to old entry";
rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
goto return_results;
}
/* Can't do it if we have kids */
rc = wt_dn2id_has_children( op, wc, e->e_id );
if( rc != WT_NOTFOUND ) {
switch( rc ) {
case 0:
Debug(LDAP_DEBUG_ARGS, "<== wt_modrdn: non-leaf %s\n", op->o_req_dn.bv_val);
rs->sr_err = LDAP_NOT_ALLOWED_ON_NONLEAF;
rs->sr_text = "subtree rename not supported";
break;
default:
Debug(LDAP_DEBUG_ARGS,
"<== wt_modrdn: has_children failed: %s (%d)\n",
wiredtiger_strerror(rc), rc );
rs->sr_err = LDAP_OTHER;
rs->sr_text = "internal error";
}
goto return_results;
}
if (!manageDSAit && is_entry_referral( e ) ) {
/* parent is a referral, don't allow add */
rs->sr_ref = get_entry_referrals( op, e );
Debug( LDAP_DEBUG_TRACE,
"wt_modrdn: entry %s is referral\n", e->e_dn );
rs->sr_err = LDAP_REFERRAL,
rs->sr_matched = e->e_name.bv_val;
send_ldap_result( op, rs );
ber_bvarray_free( rs->sr_ref );
rs->sr_ref = NULL;
rs->sr_matched = NULL;
goto done;
}
new_parent_dn = &p_dn; /* New Parent unless newSuperior given */
if ( op->oq_modrdn.rs_newSup != NULL ) {
Debug( LDAP_DEBUG_TRACE,
"wt_modrdn: new parent \"%s\" requested...\n",
op->oq_modrdn.rs_newSup->bv_val );
/* newSuperior == oldParent? */
if( dn_match( &p_ndn, op->oq_modrdn.rs_nnewSup ) ) {
Debug( LDAP_DEBUG_TRACE,
"wt_modrdn: new parent \"%s\" same as the old parent \"%s\"\n",
op->oq_modrdn.rs_newSup->bv_val, p_dn.bv_val );
op->oq_modrdn.rs_newSup = NULL; /* ignore newSuperior */
}
}
if ( op->oq_modrdn.rs_newSup != NULL ) {
if ( op->oq_modrdn.rs_newSup->bv_len ) {
np_dn = op->oq_modrdn.rs_newSup;
np_ndn = op->oq_modrdn.rs_nnewSup;
/* newSuperior == oldParent? - checked above */
/* newSuperior == entry being moved?, if so ==> ERROR */
if ( dnIsSuffix( np_ndn, &e->e_nname )) {
rs->sr_err = LDAP_NO_SUCH_OBJECT;
rs->sr_text = "new superior not found";
goto return_results;
}
/* Get Entry with dn=newSuperior. Does newSuperior exist? */
rc = wt_dn2entry(op->o_bd, wc, np_ndn, &np);
switch( rc ) {
case 0:
break;
case WT_NOTFOUND:
Debug( LDAP_DEBUG_ANY,
"<== wt_modrdn: new superior not found: %s\n",
np_ndn->bv_val );
rs->sr_err = LDAP_NO_SUCH_OBJECT;
rs->sr_text = "new superior not found";
goto return_results;
default:
Debug( LDAP_DEBUG_ANY,
"<== wt_modrdn: wt_dn2entry failed %s (%d)\n",
wiredtiger_strerror(rc), rc );
rs->sr_err = LDAP_OTHER;
rs->sr_text = "internal error";
goto return_results;
}
Debug( LDAP_DEBUG_TRACE,
"wt_modrdn: wr to new parent OK np=%p, id=%ld\n",
(void *) np, (long) np->e_id );
rs->sr_err = access_allowed( op, np, children,
NULL, ACL_WADD, NULL );
if( ! rs->sr_err ) {
Debug( LDAP_DEBUG_TRACE,
"wt_modrdn: no wr to newSup children\n" );
rs->sr_text = "no write access to new superior's children";
rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
goto return_results;
}
if ( is_entry_alias( np ) ) {
Debug( LDAP_DEBUG_TRACE,
"wt_modrdn: entry is alias\n" );
rs->sr_text = "new superior is an alias";
rs->sr_err = LDAP_ALIAS_PROBLEM;
goto return_results;
}
if ( is_entry_referral( np ) ) {
/* parent is a referral, don't allow add */
Debug( LDAP_DEBUG_TRACE,
"wt_modrdn: entry is referral\n" );
rs->sr_text = "new superior is a referral";
rs->sr_err = LDAP_OTHER;
goto return_results;
}
} else {
/* no parent, modrdn entry directly under root */
/* TODO: */
Debug( LDAP_DEBUG_TRACE,
"wt_modrdn: no parent, not implement yet\n" );
rs->sr_text = "not implement yet";
rs->sr_err = LDAP_OTHER;
goto return_results;
}
Debug( LDAP_DEBUG_TRACE,
"wt_modrdn: wr to new parent's children OK\n" );
new_parent_dn = np_dn;
}
/* Build target dn and make sure target entry doesn't exist already. */
if (!new_dn.bv_val) {
build_new_dn( &new_dn, new_parent_dn, &op->oq_modrdn.rs_newrdn, NULL );
}
if (!new_ndn.bv_val) {
struct berval bv = {0, NULL};
dnNormalize( 0, NULL, NULL, &new_dn, &bv, op->o_tmpmemctx );
ber_dupbv( &new_ndn, &bv );
/* FIXME: why not call dnNormalize() w/o ctx? */
op->o_tmpfree( bv.bv_val, op->o_tmpmemctx );
}
Debug( LDAP_DEBUG_TRACE,
"wt_modrdn: new ndn=%s\n", new_ndn.bv_val );
/* check new entry */
rc = wt_dn2entry(op->o_bd, wc, &new_ndn, &ne);
switch( rc ) {
case 0:
/* Allow rename to same DN */
if(e->e_id == ne->e_id){
break;
}
rs->sr_err = LDAP_ALREADY_EXISTS;
goto return_results;
break;
case WT_NOTFOUND:
break;
default:
Debug( LDAP_DEBUG_ANY,
"<== wt_modrdn: wt_dn2entry failed %s (%d)\n",
wiredtiger_strerror(rc), rc );
rs->sr_err = LDAP_OTHER;
rs->sr_text = "internal error";
goto return_results;
}
assert( op->orr_modlist != NULL );
if( op->o_preread ) {
if( preread_ctrl == NULL ) {
preread_ctrl = &ctrls[num_ctrls++];
ctrls[num_ctrls] = NULL;
}
if( slap_read_controls( op, rs, e,
&slap_pre_read_bv, preread_ctrl ) )
{
Debug( LDAP_DEBUG_TRACE,
"<== wt_modrdn: pre-read failed!\n" );
if ( op->o_preread & SLAP_CONTROL_CRITICAL ) {
/* FIXME: is it correct to abort
* operation if control fails? */
goto return_results;
}
}
}
/* begin transaction */
rc = wc->session->begin_transaction(wc->session, NULL);
if( rc ) {
Debug( LDAP_DEBUG_TRACE,
"wt_modrdn: begin_transaction failed: %s (%d)\n",
wiredtiger_strerror(rc), rc );
rs->sr_err = LDAP_OTHER;
rs->sr_text = "begin_transaction failed";
goto return_results;
}
wc->is_begin_transaction = 1;
Debug( LDAP_DEBUG_TRACE,
"wt_modrdn: session id: %p\n", wc->session );
/* delete old DN */
rc = wt_dn2id_delete( op, wc, &e->e_nname);
if ( rc ) {
Debug(LDAP_DEBUG_TRACE,
"<== wt_modrdn: delete failed: %s (%d)\n",
wiredtiger_strerror(rc), rc );
rs->sr_err = LDAP_OTHER;
rs->sr_text = "dn2id delete failed";
goto return_results;
}
/* copy the entry, then override some fields */
dummy = *e;
dummy.e_name = new_dn;
dummy.e_nname = new_ndn;
dummy.e_attrs = NULL;
/* add new DN */
rc = wt_dn2id_add( op, wc, np?np->e_id:p->e_id, &dummy );
if ( rc ) {
Debug(LDAP_DEBUG_TRACE,
"<== wt_modrdn: add failed: %s (%d)\n",
wiredtiger_strerror(rc), rc );
rs->sr_err = LDAP_OTHER;
rs->sr_text = "DN add failed";
goto return_results;
}
dummy.e_attrs = e->e_attrs;
rc = wt_modify_internal( op, wc, op->orm_modlist,
&dummy, &rs->sr_text, textbuf, textlen );
if( rc != LDAP_SUCCESS ) {
Debug(LDAP_DEBUG_TRACE,
"<== wt_modrdn: modify failed: %s (%d)\n",
wiredtiger_strerror(rc), rc );
if ( dummy.e_attrs == e->e_attrs ) dummy.e_attrs = NULL;
goto return_results;
}
/* update entry */
rc = wt_id2entry_update( op, wc, &dummy );
if ( rc != 0 ) {
Debug( LDAP_DEBUG_TRACE,
"wt_modrdn: id2entry update failed(%d)\n", rc );
if ( rc == LDAP_ADMINLIMIT_EXCEEDED ) {
rs->sr_text = "entry too big";
} else {
rs->sr_err = LDAP_OTHER;
rs->sr_text = "entry update failed";
}
goto return_results;
}
if ( p_ndn.bv_len != 0 ) {
parent_is_glue = is_entry_glue(p);
/* TODO: glue entry handling */
}
if( op->o_postread ) {
if( postread_ctrl == NULL ) {
postread_ctrl = &ctrls[num_ctrls++];
ctrls[num_ctrls] = NULL;
}
if( slap_read_controls( op, rs, &dummy,
&slap_post_read_bv, postread_ctrl ) )
{
Debug( LDAP_DEBUG_TRACE,
"<== wt_modrdn: post-read failed!\n" );
if ( op->o_postread & SLAP_CONTROL_CRITICAL ) {
/* FIXME: is it correct to abort
* operation if control fails? */
goto return_results;
}
}
}
if( op->o_noop ) {
rs->sr_err = LDAP_X_NO_OPERATION;
goto return_results;
}
rc = wc->session->commit_transaction(wc->session, NULL);
wc->is_begin_transaction = 0;
if( rc ) {
Debug( LDAP_DEBUG_TRACE,
"<== wt_modrdn: commit failed: %s (%d)\n",
wiredtiger_strerror(rc), rc );
rs->sr_err = LDAP_OTHER;
rs->sr_text = "commit failed";
goto return_results;
}
Debug(LDAP_DEBUG_TRACE,
"wt_modrdn: rdn modified%s id=%08lx dn=\"%s\"\n",
op->o_noop ? " (no-op)" : "",
dummy.e_id, op->o_req_dn.bv_val );
rs->sr_err = LDAP_SUCCESS;
rs->sr_text = NULL;
if( num_ctrls ) rs->sr_ctrls = ctrls;
return_results:
if ( dummy.e_attrs ) {
attrs_free( dummy.e_attrs );
}
send_ldap_result( op, rs );
if ( rs->sr_err == LDAP_SUCCESS && parent_is_glue && parent_is_leaf ) {
op->o_delete_glue_parent = 1;
}
done:
if( wc && wc->is_begin_transaction ){
Debug( LDAP_DEBUG_TRACE, "wt_modrdn: rollback transaction\n" );
wc->session->rollback_transaction(wc->session, NULL);
wc->is_begin_transaction = 0;
}
slap_graduate_commit_csn( op );
if( new_dn.bv_val != NULL ) free( new_dn.bv_val );
if( new_ndn.bv_val != NULL ) free( new_ndn.bv_val );
/* free entry */
if( e != NULL ) {
wt_entry_return( e );
}
/* free parent entry */
if( p != NULL ) {
wt_entry_return( p );
}
/* free new entry */
if( ne != NULL ) {
wt_entry_return( ne );
}
/* free new parent entry */
if( np != NULL ) {
wt_entry_return( np );
}
if( preread_ctrl != NULL && (*preread_ctrl) != NULL ) {
slap_sl_free( (*preread_ctrl)->ldctl_value.bv_val, op->o_tmpmemctx );
slap_sl_free( *preread_ctrl, op->o_tmpmemctx );
}
if( postread_ctrl != NULL && (*postread_ctrl) != NULL ) {
slap_sl_free( (*postread_ctrl)->ldctl_value.bv_val, op->o_tmpmemctx );
slap_sl_free( *postread_ctrl, op->o_tmpmemctx );
}
return rs->sr_err;
}
/*
* Local variables:
* indent-tabs-mode: t
* tab-width: 4
* c-basic-offset: 4
* End:
*/

View file

@ -41,8 +41,7 @@ int wt_last_id( BackendDB *be, WT_SESSION *session, ID *out )
rc = session->open_cursor(session, WT_TABLE_ID2ENTRY, NULL, NULL, &cursor);
if(rc){
Debug( LDAP_DEBUG_ANY,
LDAP_XSTRING(wt_last_id)
": open_cursor failed: %s (%d)\n",
"wt_last_id: open_cursor failed: %s (%d)\n",
wiredtiger_strerror(rc), rc );
return rc;
}
@ -53,8 +52,7 @@ int wt_last_id( BackendDB *be, WT_SESSION *session, ID *out )
rc = cursor->get_key(cursor, &id);
if ( rc ) {
Debug( LDAP_DEBUG_ANY,
LDAP_XSTRING(wt_last_id)
": get_key failed: %s (%d)\n",
"wt_last_id: get_key failed: %s (%d)\n",
wiredtiger_strerror(rc), rc );
return rc;
}
@ -66,16 +64,14 @@ int wt_last_id( BackendDB *be, WT_SESSION *session, ID *out )
break;
default:
Debug( LDAP_DEBUG_ANY,
LDAP_XSTRING(wt_last_id)
": prev failed: %s (%d)\n",
"wt_last_id: prev failed: %s (%d)\n",
wiredtiger_strerror(rc), rc );
}
rc = cursor->close(cursor);
if ( rc ) {
Debug( LDAP_DEBUG_ANY,
LDAP_XSTRING(wt_last_id)
": close failed: %s (%d)\n",
"wt_last_id: close failed: %s (%d)\n",
wiredtiger_strerror(rc), rc );
return rc;
}

View file

@ -42,12 +42,11 @@ wt_hasSubordinates(
wc = wt_ctx_get(op, wi);
if( !wc ){
Debug( LDAP_DEBUG_ANY,
LDAP_XSTRING(wt_compare)
": wt_ctx_get failed\n" );
"wt_hasSubordinates: wt_ctx_get failed\n" );
return LDAP_OTHER;
}
rc = wt_dn2id_has_children(op, wc->session, e->e_id);
rc = wt_dn2id_has_children(op, wc, e->e_id);
switch(rc){
case 0:
*hasSubordinates = LDAP_COMPARE_TRUE;
@ -58,8 +57,7 @@ wt_hasSubordinates(
break;
default:
Debug(LDAP_DEBUG_ANY,
"<=- " LDAP_XSTRING(wt_hasSubordinates)
": has_children failed: %s (%d)\n",
"<=- wt_hasSubordinates: has_children failed: %s (%d)\n",
wiredtiger_strerror(rc), rc );
rc = LDAP_OTHER;
}

View file

@ -26,15 +26,29 @@ LDAP_BEGIN_DECL
#define WT_UCTYPE "WT"
/*
* attr.c
*/
AttrInfo *wt_attr_mask( struct wt_info *wi, AttributeDescription *desc );
void wt_attr_flush( struct wt_info *wi );
void wt_attr_index_unparse( struct wt_info *wi, BerVarray *bva );
int wt_attr_index_config(
struct wt_info *wi,
const char *fname,
int lineno,
int argc,
char **argv,
struct config_reply_s *c_reply);
void wt_attr_index_destroy( struct wt_info *wi );
/*
* id2entry.c
*/
int wt_id2entry_add(Operation *op, WT_SESSION *session, Entry *e );
int wt_id2entry_update(Operation *op, WT_SESSION *session, Entry *e );
int wt_id2entry_delete(Operation *op, WT_SESSION *session, Entry *e );
int wt_id2entry(BackendDB *be, wt_ctx *wc, ID id, Entry **ep );
int wt_id2entry_add(Operation *op, wt_ctx *wc, Entry *e );
int wt_id2entry_update(Operation *op, wt_ctx *wc, Entry *e );
int wt_id2entry_delete(Operation *op, wt_ctx *wc, Entry *e );
BI_entry_release_rw wt_entry_release;
BI_entry_get_rw wt_entry_get;
@ -50,12 +64,47 @@ unsigned wt_idl_search( ID *ids, ID id );
ID wt_idl_first( ID *ids, ID *cursor );
ID wt_idl_next( ID *ids, ID *cursor );
int wt_idl_append_one( ID *ids, ID id );
void wt_idl_sort( ID *ids, ID *tmp );
int wt_idl_intersection( ID *a, ID *b );
int wt_filter_candidates(
Operation *op,
wt_ctx *wc,
Filter *f,
ID *ids,
ID *tmp,
ID *stack );
int
wt_idl_union(
ID *a,
ID *b );
/*
* index.c
*/
extern AttrInfo *
wt_index_mask LDAP_P((
Backend *be,
AttributeDescription *desc,
struct berval *atname ));
int wt_index_entry LDAP_P(( Operation *op, wt_ctx *wc, int r, Entry *e ));
int wt_index_values(
Operation *op,
wt_ctx *wc,
AttributeDescription *desc,
BerVarray vals,
ID id,
int opid );
int wt_index_param(
Backend *be,
AttributeDescription *desc,
int ftype,
slap_mask_t *maskp,
struct berval *prefixp );
WT_CURSOR *wt_index_open(wt_ctx *wc, struct berval *name, int create);
#define wt_index_entry_add(op,t,e) \
wt_index_entry((op),(t),SLAP_INDEX_ADD_OP,(e))
@ -110,23 +159,38 @@ int wt_back_init_cf( BackendInfo *bi );
int
wt_dn2id(
Operation *op,
WT_SESSION *session,
wt_ctx *wc,
struct berval *ndn,
ID *id);
int
wt_dn2id_add(
Operation *op,
WT_SESSION *session,
wt_ctx *wc,
ID pid,
Entry *e);
int
wt_dn2idl(
Operation *op,
wt_ctx *wc,
struct berval *ndn,
Entry *e,
ID *ids,
ID *stack);
int
wt_dn2id_delete(
Operation *op,
WT_SESSION *session,
wt_ctx *wc,
struct berval *ndn);
int
wt_dn2id_has_children(
Operation *op,
wt_ctx *wc,
ID id );
/*
* dn2entry.c
*/
@ -139,6 +203,10 @@ int wt_dn2pentry( BackendDB *be,
wt_ctx *wc,
struct berval *ndn,
Entry **ep );
int wt_dn2aentry( BackendDB *be,
wt_ctx *wc,
struct berval *ndn,
Entry **ep );
/*
* former ctx.c
@ -146,8 +214,14 @@ int wt_dn2pentry( BackendDB *be,
wt_ctx *wt_ctx_init(struct wt_info *wi);
void wt_ctx_free(void *key, void *data);
wt_ctx *wt_ctx_get(Operation *op, struct wt_info *wi);
WT_CURSOR *wt_ctx_index_cursor(wt_ctx *wc, struct berval *name, int create);
/*
* former cache.c
*/
int wt_idlcache_get(wt_ctx *wc, struct berval *ndn, int scope, ID *ids);
int wt_idlcache_set(wt_ctx *wc, struct berval *ndn, int scope, ID *ids);
int wt_idlcache_begin(wt_ctx *wc, struct berval *ndn, int scope);
int wt_idlcache_clear(Operation *op, wt_ctx *wc, struct berval *ndn);
/*
* former external.h
@ -159,13 +233,16 @@ extern BI_op_add wt_add;
extern BI_op_bind wt_bind;
extern BI_op_compare wt_compare;
extern BI_op_delete wt_delete;
extern BI_op_delete wt_modify;
extern BI_op_modify wt_modify;
extern BI_op_modrdn wt_modrdn;
extern BI_op_search wt_search;
extern BI_op_extended wt_extended;
extern BI_operational wt_operational;
extern BI_has_subordinates wt_hasSubordinates;
/* tools.c */
int wt_entry_header(WT_ITEM *item, EntryHeader *eh);
extern BI_tool_entry_open wt_tool_entry_open;
extern BI_tool_entry_close wt_tool_entry_close;
extern BI_tool_entry_first_x wt_tool_entry_first_x;
@ -175,6 +252,7 @@ extern BI_tool_entry_put wt_tool_entry_put;
extern BI_tool_entry_reindex wt_tool_entry_reindex;
extern BI_tool_dn2id_get wt_tool_dn2id_get;
extern BI_tool_entry_modify wt_tool_entry_modify;
extern BI_tool_entry_delete wt_tool_entry_delete;
LDAP_END_DECL

View file

@ -47,8 +47,7 @@ static int base_candidate(
ID *ids )
{
Debug(LDAP_DEBUG_ARGS,
LDAP_XSTRING(base_candidate)
": base: \"%s\" (0x%08lx)\n",
"base_candidate: base: \"%s\" (0x%08lx)\n",
e->e_nname.bv_val, (long) e->e_id );
ids[0] = 1;
@ -138,8 +137,7 @@ static int search_candidates(
AttributeAssertion aa_subentry = ATTRIBUTEASSERTION_INIT;
Debug(LDAP_DEBUG_TRACE,
LDAP_XSTRING(wt_search_candidates)
": base=\"%s\" (0x%08lx) scope=%d\n",
"wt_search_candidates: base=\"%s\" (0x%08lx) scope=%d\n",
e->e_nname.bv_val, (long) e->e_id, op->oq_search.rs_scope );
xf.f_or = op->oq_search.rs_filter;
@ -195,9 +193,9 @@ static int search_candidates(
if( op->ors_deref & LDAP_DEREF_SEARCHING ) {
rc = search_aliases( op, rs, e, wc->session, ids, scopes, stack );
if ( WT_IDL_IS_ZERO( ids ) && rc == LDAP_SUCCESS )
rc = wt_dn2idl( op, wc->session, &e->e_nname, e, ids, stack );
rc = wt_dn2idl( op, wc, &e->e_nname, e, ids, stack );
} else {
rc = wt_dn2idl(op, wc->session, &e->e_nname, e, ids, stack );
rc = wt_dn2idl(op, wc, &e->e_nname, e, ids, stack );
}
if ( rc == LDAP_SUCCESS ) {
@ -211,14 +209,11 @@ static int search_candidates(
if( rc ) {
Debug(LDAP_DEBUG_TRACE,
LDAP_XSTRING(wt_search_candidates)
": failed (rc=%d)\n",
rc );
"wt_search_candidates: failed (rc=%d)\n", rc );
} else {
Debug(LDAP_DEBUG_TRACE,
LDAP_XSTRING(wt_search_candidates)
": id=%ld first=%ld last=%ld\n",
"wt_search_candidates: id=%ld first=%ld last=%ld\n",
(long) ids[0],
(long) WT_IDL_FIRST(ids),
(long) WT_IDL_LAST(ids));
@ -247,7 +242,7 @@ parse_paged_cookie( Operation *op, SlapReply *rs )
goto done;
}
AC_MEMCPY( &reqcookie, ps->ps_cookieval.bv_val, sizeof( reqcookie ));
memcpy( &reqcookie, ps->ps_cookieval.bv_val, sizeof( reqcookie ));
if ( reqcookie > ps->ps_cookie ) {
/* bad cookie */
@ -285,8 +280,7 @@ send_paged_response(
struct berval cookie;
Debug(LDAP_DEBUG_ARGS,
LDAP_XSTRING(send_paged_response)
": lastid=0x%08lx nentries=%d\n",
"send_paged_response: lastid=0x%08lx nentries=%d\n",
lastid ? *lastid : 0, rs->sr_nentries );
ctrls[1] = NULL;
@ -333,34 +327,28 @@ wt_search( Operation *op, SlapReply *rs )
struct wt_info *wi = (struct wt_info *) op->o_bd->be_private;
ID id, cursor;
ID lastid = NOID;
AttributeName *attrs;
OpExtra *oex;
int manageDSAit;
wt_ctx *wc;
int rc;
int rc = LDAP_OTHER;
Entry *e = NULL;
Entry *ae = NULL;
Entry *base = NULL;
slap_mask_t mask;
time_t stoptime;
ID candidates[WT_IDL_UM_SIZE];
ID iscopes[WT_IDL_DB_SIZE];
ID scopes[WT_IDL_DB_SIZE];
int tentries = 0;
unsigned nentries = 0;
Debug( LDAP_DEBUG_ARGS, "==> " LDAP_XSTRING(wt_search) ": %s\n",
op->o_req_dn.bv_val );
attrs = op->oq_search.rs_attrs;
Debug( LDAP_DEBUG_ARGS, "==> wt_search: %s\n", op->o_req_dn.bv_val );
manageDSAit = get_manageDSAit( op );
wc = wt_ctx_get(op, wi);
if( !wc ){
Debug( LDAP_DEBUG_ANY,
LDAP_XSTRING(wt_search)
": wt_ctx_get failed: %d\n",
rc );
"wt_search: wt_ctx_get failed: %d\n", rc );
send_ldap_error( op, rs, LDAP_OTHER, "internal error" );
return rc;
}
@ -371,20 +359,12 @@ wt_search( Operation *op, SlapReply *rs )
case 0:
break;
case WT_NOTFOUND:
Debug( LDAP_DEBUG_ARGS,
"<== " LDAP_XSTRING(wt_search)
": no such object %s\n",
op->o_req_dn.bv_val );
rs->sr_err = LDAP_REFERRAL;
rs->sr_flags = REP_MATCHED_MUSTBEFREED | REP_REF_MUSTBEFREED;
send_ldap_result( op, rs );
goto done;
rc = wt_dn2aentry(op->o_bd, wc, &op->o_req_ndn, &ae);
break;
default:
/* TODO: error handling */
Debug( LDAP_DEBUG_ANY,
LDAP_XSTRING(wt_delete)
": error at wt_dn2entry() rc=%d\n",
rc );
"<== wt_search: error at wt_dn2entry() rc=%d\n", rc );
send_ldap_error( op, rs, LDAP_OTHER, "internal error" );
goto done;
}
@ -394,7 +374,37 @@ wt_search( Operation *op, SlapReply *rs )
}
if ( e == NULL ) {
// TODO
if ( ae ) {
struct berval matched_dn = BER_BVNULL;
/* found ancestor entry */
if ( access_allowed( op, ae,
slap_schema.si_ad_entry,
NULL, ACL_DISCLOSE, NULL ) ) {
BerVarray erefs = NULL;
ber_dupbv( &matched_dn, &ae->e_name );
erefs = is_entry_referral( ae )
? get_entry_referrals( op, ae )
: NULL;
rs->sr_err = LDAP_REFERRAL;
rs->sr_matched = matched_dn.bv_val;
if ( erefs ) {
rs->sr_ref = referral_rewrite( erefs, &matched_dn,
&op->o_req_dn, op->oq_search.rs_scope );
ber_bvarray_free( erefs );
}
Debug( LDAP_DEBUG_ARGS,
"wt_search: ancestor is referral\n");
rs->sr_flags = REP_MATCHED_MUSTBEFREED | REP_REF_MUSTBEFREED;
send_ldap_result( op, rs );
goto done;
}
}
Debug( LDAP_DEBUG_ARGS,
"wt_search: no such object %s\n",
op->o_req_dn.bv_val);
rs->sr_err = LDAP_NO_SUCH_OBJECT;
send_ldap_result( op, rs );
goto done;
}
/* NOTE: __NEW__ "search" access is required
@ -413,8 +423,27 @@ wt_search( Operation *op, SlapReply *rs )
}
if ( !manageDSAit && is_entry_referral( e ) ) {
/* entry is a referral */
/* TODO: */
struct berval matched_dn = BER_BVNULL;
BerVarray erefs = NULL;
ber_dupbv( &matched_dn, &e->e_name );
erefs = get_entry_referrals( op, e );
rs->sr_err = LDAP_REFERRAL;
if ( erefs ) {
rs->sr_ref = referral_rewrite( erefs, &matched_dn,
&op->o_req_dn, op->oq_search.rs_scope );
ber_bvarray_free( erefs );
if ( !rs->sr_ref ) {
rs->sr_text = "bad_referral object";
}
}
Debug( LDAP_DEBUG_ARGS, "wt_search: entry is referral\n");
rs->sr_matched = matched_dn.bv_val;
send_ldap_result( op, rs );
ber_bvarray_free( rs->sr_ref );
rs->sr_ref = NULL;
ber_memfree( matched_dn.bv_val );
rs->sr_matched = NULL;
goto done;
}
if ( get_assert( op ) &&
@ -445,8 +474,7 @@ wt_search( Operation *op, SlapReply *rs )
case WT_NOTFOUND:
break;
default:
Debug( LDAP_DEBUG_ANY,
LDAP_XSTRING(wt_search) ": error search_candidates\n" );
Debug( LDAP_DEBUG_ANY, "wt_search: error search_candidates\n" );
send_ldap_error( op, rs, LDAP_OTHER, "internal error" );
goto done;
}
@ -457,8 +485,7 @@ wt_search( Operation *op, SlapReply *rs )
cursor = 0;
if ( candidates[0] == 0 ) {
Debug( LDAP_DEBUG_TRACE,
LDAP_XSTRING(wt_search) ": no candidates\n" );
Debug( LDAP_DEBUG_TRACE, "wt_search: no candidates\n" );
goto nochange;
}
@ -497,9 +524,7 @@ wt_search( Operation *op, SlapReply *rs )
}
id = wt_idl_first( candidates, &cursor );
if ( id == NOID ) {
Debug( LDAP_DEBUG_TRACE,
LDAP_XSTRING(wt_search)
": no paged results candidates\n" );
Debug( LDAP_DEBUG_TRACE, "wt_search: no paged results candidates\n" );
send_paged_response( op, rs, &lastid, 0 );
rs->sr_err = LDAP_OTHER;
@ -549,7 +574,7 @@ loop_begin:
fetch_entry_retry:
rc = wt_id2entry(op->o_bd, wc->session, id, &e);
rc = wt_id2entry(op->o_bd, wc, id, &e);
/* TODO: error handling */
if ( e == NULL ) {
/* TODO: */
@ -583,8 +608,11 @@ loop_begin:
case LDAP_SCOPE_ONELEVEL:
scopeok = 1;
break;
case LDAP_SCOPE_CHILDREN:
if ( id == base->e_id ) break;
/* Fall-thru */
case LDAP_SCOPE_SUBTREE:
scopeok = 1;
scopeok = dnIsSuffix(&e->e_nname, &base->e_nname);
break;
}
@ -605,9 +633,7 @@ loop_begin:
/* Not in scope, ignore it */
if ( !scopeok )
{
Debug( LDAP_DEBUG_TRACE,
LDAP_XSTRING(wt_search)
": %ld scope not okay\n",
Debug( LDAP_DEBUG_TRACE, "wt_search: %ld scope not okay\n",
(long) id );
goto loop_continue;
}
@ -620,7 +646,16 @@ loop_begin:
if ( !manageDSAit && op->oq_search.rs_scope != LDAP_SCOPE_BASE
&& is_entry_referral( e ) )
{
/* TODO: referral */
BerVarray erefs = get_entry_referrals( op, e );
rs->sr_ref = referral_rewrite( erefs, &e->e_name, NULL,
op->oq_search.rs_scope == LDAP_SCOPE_ONELEVEL
? LDAP_SCOPE_BASE : LDAP_SCOPE_SUBTREE );
rs->sr_entry = e;
send_search_reference( op, rs );
rs->sr_entry = NULL;
ber_bvarray_free( rs->sr_ref );
ber_bvarray_free( erefs );
goto loop_continue;
}
if ( !manageDSAit && is_entry_glue( e )) {
@ -632,7 +667,13 @@ loop_begin:
if ( rs->sr_err == LDAP_COMPARE_TRUE ) {
/* check size limit */
if ( get_pagedresults(op) > SLAP_CONTROL_IGNORED ) {
/* TODO: */
if ( rs->sr_nentries >= ((PagedResultsState *)op->o_pagedresults_state)->ps_size ) {
wt_entry_return( e );
e = NULL;
send_paged_response( op, rs, &lastid, tentries );
goto done;
}
lastid = id;
}
if (e) {
@ -648,19 +689,28 @@ loop_begin:
rs->sr_attrs = NULL;
rs->sr_entry = NULL;
e = NULL;
}
switch ( rs->sr_err ) {
case LDAP_SUCCESS: /* entry sent ok */
break;
default:
/* TODO: error handling */
break;
switch ( rs->sr_err ) {
case LDAP_SUCCESS: /* entry sent ok */
break;
default: /* entry not sent */
break;
case LDAP_BUSY:
send_ldap_result( op, rs );
goto done;
case LDAP_UNAVAILABLE:
rs->sr_err = LDAP_OTHER;
goto done;
case LDAP_SIZELIMIT_EXCEEDED:
rs->sr_ref = rs->sr_v2ref;
send_ldap_result( op, rs );
rs->sr_err = LDAP_SUCCESS;
goto done;
}
}
} else {
Debug( LDAP_DEBUG_TRACE,
LDAP_XSTRING(wt_search)
": %ld does not match filter\n",
(long) id );
"wt_search: %ld does not match filter\n", (long) id );
}
loop_continue:
@ -676,8 +726,7 @@ nochange:
rs->sr_err = (rs->sr_v2ref == NULL) ? LDAP_SUCCESS : LDAP_REFERRAL;
rs->sr_rspoid = NULL;
if ( get_pagedresults(op) > SLAP_CONTROL_IGNORED ) {
/* not implement yet */
/* send_paged_response( op, rs, NULL, 0 ); */
send_paged_response( op, rs, NULL, 0 );
} else {
send_ldap_result( op, rs );
}
@ -694,6 +743,10 @@ done:
wt_entry_return( e );
}
if( ae ) {
wt_entry_return( ae );
}
return rs->sr_err;
}

View file

@ -33,15 +33,11 @@ typedef struct dn_id {
#define HOLE_SIZE 4096
static dn_id hbuf[HOLE_SIZE], *holes = hbuf;
static unsigned nhmax = HOLE_SIZE;
static unsigned nholes;
static int index_nattrs;
static struct berval *tool_base;
static int tool_scope;
static Filter *tool_filter;
static Entry *tool_next_entry;
static wt_ctx *wc;
static WT_CURSOR *reader;
@ -51,14 +47,12 @@ int
wt_tool_entry_open( BackendDB *be, int mode )
{
struct wt_info *wi = (struct wt_info *) be->be_private;
WT_CONNECTION *conn = wi->wi_conn;
int rc;
wc = wt_ctx_init(wi);
if( !wc ){
Debug( LDAP_DEBUG_ANY,
LDAP_XSTRING(wt_tool_entry_open)
": wt_ctx_get failed\n" );
"wt_tool_entry_open: wt_ctx_get failed\n" );
return -1;
}
@ -66,8 +60,7 @@ wt_tool_entry_open( BackendDB *be, int mode )
,NULL, NULL, &reader);
if ( rc ) {
Debug( LDAP_DEBUG_ANY,
LDAP_XSTRING(wt_tool_entry_open)
": cursor open failed: %s (%d)\n",
"wt_tool_entry_open: cursor open failed: %s (%d)\n",
wiredtiger_strerror(rc), rc );
return -1;
}
@ -78,8 +71,6 @@ wt_tool_entry_open( BackendDB *be, int mode )
int
wt_tool_entry_close( BackendDB *be )
{
int rc;
if( reader ) {
reader->close(reader);
reader = NULL;
@ -127,8 +118,7 @@ wt_tool_entry_next( BackendDB *be )
return NOID;
default:
Debug( LDAP_DEBUG_ANY,
LDAP_XSTRING(wt_tool_entry_next)
": next failed: %s (%d)\n",
"wt_tool_entry_next: next failed: %s (%d)\n",
wiredtiger_strerror(rc), rc );
return NOID;
}
@ -136,16 +126,7 @@ wt_tool_entry_next( BackendDB *be )
rc = reader->get_key(reader, &id);
if( rc ){
Debug( LDAP_DEBUG_ANY,
LDAP_XSTRING(wt_tool_entry_next)
": get_key failed: %s (%d)\n",
wiredtiger_strerror(rc), rc );
}
rc = reader->get_value(reader, &item);
if( rc ){
Debug( LDAP_DEBUG_ANY,
LDAP_XSTRING(wt_tool_entry_next)
": get_value failed: %s (%d)\n",
"wt_tool_entry_next: get_key failed: %s (%d)\n",
wiredtiger_strerror(rc), rc );
}
return id;
@ -169,7 +150,8 @@ entry_getlen(unsigned char **buf)
return len;
}
int wt_entry_header(WT_ITEM *item, EntryHeader *eh){
int wt_entry_header(WT_ITEM *item, EntryHeader *eh)
{
unsigned char *ptr = (unsigned char *)item->data;
/* Some overlays can create empty entries
@ -191,6 +173,22 @@ wt_tool_entry_get( BackendDB *be, ID id )
assert( be != NULL );
assert( slapMode & SLAP_TOOL_MODE );
reader->set_key(reader, id);
rc = reader->search(reader);
if ( rc ) {
Debug( LDAP_DEBUG_ANY,
"wt_tool_entry_get: search failed: %s (%d)\n",
wiredtiger_strerror(rc), rc );
goto done;
}
rc = reader->get_value(reader, &item);
if( rc ){
Debug( LDAP_DEBUG_ANY,
"wt_tool_entry_get: get_value failed: %s (%d)\n",
wiredtiger_strerror(rc), rc );
goto done;
}
rc = wt_entry_header( &item, &eh );
assert( rc == 0 );
eoff = eh.data - (char *)item.data;
@ -209,6 +207,7 @@ wt_tool_entry_get( BackendDB *be, ID id )
e->e_id = id;
}
done:
return e;
}
@ -218,7 +217,6 @@ static int wt_tool_next_id(
struct berval *text,
int hole )
{
struct wt_info *wi = (struct wt_info *) op->o_bd->be_private;
struct berval dn = e->e_name;
struct berval ndn = e->e_nname;
struct berval pdn, npdn;
@ -231,7 +229,7 @@ static int wt_tool_next_id(
return 0;
}
rc = wt_dn2id(op, wc->session, &ndn, &id);
rc = wt_dn2id(op, wc, &ndn, &id);
if(rc == 0){
e->e_id = id;
}else if( rc == WT_NOTFOUND ){
@ -258,7 +256,7 @@ static int wt_tool_next_id(
pid = id;
}
wt_next_id( op->o_bd, &e->e_id );
rc = wt_dn2id_add(op, wc->session, pid, e);
rc = wt_dn2id_add(op, wc, pid, e);
if( rc ){
snprintf( text->bv_val, text->bv_len,
"wt_dn2id_add failed: %s (%d)",
@ -298,11 +296,9 @@ wt_tool_index_add(
ID
wt_tool_entry_put( BackendDB *be, Entry *e, struct berval *text )
{
struct wt_info *wi = (struct wt_info *) be->be_private;
int rc;
Operation op = {0};
Opheader ohdr = {0};
Operation op = {0};
Opheader ohdr = {0};
assert( slapMode & SLAP_TOOL_MODE );
assert( text != NULL );
@ -310,14 +306,12 @@ wt_tool_entry_put( BackendDB *be, Entry *e, struct berval *text )
assert( text->bv_val[0] == '\0' ); /* overconservative? */
Debug( LDAP_DEBUG_TRACE,
"=> " LDAP_XSTRING(wt_tool_entry_put)
": ( \"%s\" )\n", e->e_dn );
"=> wt_tool_entry_put: ( \"%s\" )\n", e->e_dn );
rc = wc->session->begin_transaction(wc->session, NULL);
if( rc ){
Debug( LDAP_DEBUG_ANY,
LDAP_XSTRING(wt_dn2id_add)
": begin_transaction failed: %s (%d)\n",
"wt_dn2id_add: begin_transaction failed: %s (%d)\n",
wiredtiger_strerror(rc), rc );
return NOID;
}
@ -333,18 +327,17 @@ wt_tool_entry_put( BackendDB *be, Entry *e, struct berval *text )
"wt_tool_next_id failed: %s (%d)",
wiredtiger_strerror(rc), rc );
Debug( LDAP_DEBUG_ANY,
"=> " LDAP_XSTRING(wt_tool_entry_put) ": %s\n",
text->bv_val );
"=> wt_tool_entry_put: %s\n", text->bv_val );
goto done;
}
rc = wt_id2entry_add( &op, wc->session, e );
rc = wt_id2entry_add( &op, wc, e );
if( rc != 0 ) {
snprintf( text->bv_val, text->bv_len,
"id2entry_add failed: %s (%d)",
wiredtiger_strerror(rc), rc );
Debug( LDAP_DEBUG_ANY,
"=> " LDAP_XSTRING(wt_tool_entry_put) ": %s\n",
"=> wt_tool_entry_put: %s\n",
text->bv_val );
goto done;
}
@ -356,8 +349,7 @@ wt_tool_entry_put( BackendDB *be, Entry *e, struct berval *text )
rc == LDAP_OTHER ? "Internal error" :
wiredtiger_strerror(rc), rc );
Debug( LDAP_DEBUG_ANY,
"=> " LDAP_XSTRING(wt_tool_entry_put) ": %s\n",
text->bv_val );
"=> wt_tool_entry_put: %s\n", text->bv_val );
goto done;
}
@ -369,8 +361,7 @@ done:
"txn_commit failed: %s (%d)",
wiredtiger_strerror(rc), rc );
Debug( LDAP_DEBUG_ANY,
"=> " LDAP_XSTRING(wt_tool_entry_put) ": %s\n",
text->bv_val );
"=> wt_tool_entry_put: %s\n", text->bv_val );
e->e_id = NOID;
}
}else{
@ -380,8 +371,7 @@ done:
rc == LDAP_OTHER ? "Internal error" :
wiredtiger_strerror(rc), rc );
Debug( LDAP_DEBUG_ANY,
"=> " LDAP_XSTRING(wt_tool_entry_put) ": %s\n",
text->bv_val );
"=> wt_tool_entry_put: %s\n", text->bv_val );
e->e_id = NOID;
}
@ -400,8 +390,7 @@ int wt_tool_entry_reindex(
Opheader ohdr = {0};
Debug( LDAP_DEBUG_ARGS,
"=> " LDAP_XSTRING(wt_tool_entry_reindex) "( %ld )\n",
(long) id );
"=> wt_tool_entry_reindex( %ld )\n", (long) id );
assert( tool_base == NULL );
assert( tool_filter == NULL );
@ -443,8 +432,7 @@ int wt_tool_entry_reindex(
}
if ( j == wi->wi_nattrs ) {
Debug( LDAP_DEBUG_ANY,
LDAP_XSTRING(wt_tool_entry_reindex)
": no index configured for %s\n",
"wt_tool_entry_reindex: no index configured for %s\n",
adv[i]->ad_cname.bv_val );
return -1;
}
@ -456,8 +444,7 @@ int wt_tool_entry_reindex(
e = wt_tool_entry_get( be, id );
if( e == NULL ) {
Debug( LDAP_DEBUG_ANY,
LDAP_XSTRING(wt_tool_entry_reindex)
Debug( LDAP_DEBUG_ANY, "=> wt_tool_entry_reindex"
": could not locate id=%ld\n",
(long) id );
return -1;
@ -471,13 +458,12 @@ int wt_tool_entry_reindex(
rc = wc->session->begin_transaction(wc->session, NULL);
if( rc ){
Debug( LDAP_DEBUG_ANY,
LDAP_XSTRING(wt_dn2id_add)
": begin_transaction failed: %s (%d)\n",
"wt_tool_entry_reindex: begin_transaction failed %s (%d)\n",
wiredtiger_strerror(rc), rc );
goto done;
}
Debug( LDAP_DEBUG_TRACE,
"=> " LDAP_XSTRING(wt_tool_entry_reindex) "( %ld, \"%s\" )\n",
"=> wt_tool_entry_reindex( %ld, \"%s\" )\n",
(long) id, e->e_dn );
rc = wt_tool_index_add( &op, wc, e );
@ -487,15 +473,13 @@ done:
rc = wc->session->commit_transaction(wc->session, NULL);
if( rc ) {
Debug( LDAP_DEBUG_ANY,
"=> " LDAP_XSTRING(wt_tool_entry_reindex)
"commit_transaction failed: %s (%d)\n",
"=> wt_tool_entry_reindex: commit_transaction failed %s (%d)\n",
wiredtiger_strerror(rc), rc );
}
}else{
rc = wc->session->rollback_transaction(wc->session, NULL);
Debug( LDAP_DEBUG_ANY,
"=> " LDAP_XSTRING(wt_tool_entry_reindex)
": rollback transaction %s (%d)\n",
"=> wt_tool_entry_reindex: rollback transaction %s (%d)\n",
wiredtiger_strerror(rc), rc );
}
@ -504,6 +488,221 @@ done:
return rc;
}
ID wt_tool_dn2id_get(
Backend *be,
struct berval *dn
)
{
Operation op = {0};
Opheader ohdr = {0};
ID id;
int rc;
if ( BER_BVISEMPTY(dn) )
return 0;
op.o_hdr = &ohdr;
op.o_bd = be;
op.o_tmpmemctx = NULL;
op.o_tmpmfuncs = &ch_mfuncs;
rc = wt_dn2id(&op, wc, dn, &id);
switch( rc ){
case 0:
break;
case WT_NOTFOUND:
return NOID;
default:
Debug( LDAP_DEBUG_ANY,
"wt_tool_entry_get: entry get failed: %s (%d)\n",
wiredtiger_strerror(rc), rc );
return NOID;
}
return id;
}
ID wt_tool_entry_modify(
BackendDB *be,
Entry *e,
struct berval *text )
{
int rc;
Operation op = {0};
Opheader ohdr = {0};
assert( be != NULL );
assert( slapMode & SLAP_TOOL_MODE );
assert( text != NULL );
assert( text->bv_val != NULL );
assert( text->bv_val[0] == '\0' ); /* overconservative? */
assert ( e->e_id != NOID );
Debug( LDAP_DEBUG_TRACE,
"=> wt_tool_entry_modify( %ld, \"%s\" )\n",
(long) e->e_id, e->e_dn );
rc = wc->session->begin_transaction(wc->session, NULL);
if( rc ){
Debug( LDAP_DEBUG_ANY, "=> wt_tool_entry_modify"
": begin_transaction failed: %s (%d)\n",
wiredtiger_strerror(rc), rc );
return NOID;
}
op.o_hdr = &ohdr;
op.o_bd = be;
op.o_tmpmemctx = NULL;
op.o_tmpmfuncs = &ch_mfuncs;
rc = wt_id2entry_update( &op, wc, e );
if( rc != 0 ) {
snprintf( text->bv_val, text->bv_len,
"id2entry_update failed: %s (%d)",
wiredtiger_strerror(rc), rc );
Debug( LDAP_DEBUG_ANY, "=> wt_tool_entry_modify: %s\n",
text->bv_val );
goto done;
}
done:
if ( rc == 0 ){
rc = wc->session->commit_transaction(wc->session, NULL);
if( rc != 0 ) {
snprintf( text->bv_val, text->bv_len,
"txn_commit failed: %s (%d)",
wiredtiger_strerror(rc), rc );
Debug( LDAP_DEBUG_ANY, "=> wt_tool_entry_modify: %s\n",
text->bv_val );
e->e_id = NOID;
}
}else{
rc = wc->session->rollback_transaction(wc->session, NULL);
snprintf( text->bv_val, text->bv_len,
"txn_aborted! %s (%d)",
rc == LDAP_OTHER ? "Internal error" :
wiredtiger_strerror(rc), rc );
Debug( LDAP_DEBUG_ANY, "=> wt_tool_entry_modify: %s\n",
text->bv_val );
e->e_id = NOID;
}
return e->e_id;
}
int wt_tool_entry_delete(
BackendDB *be,
struct berval *ndn,
struct berval *text )
{
struct wt_info *wi = (struct wt_info *) be->be_private;
int rc;
Operation op = {0};
Opheader ohdr = {0};
Entry *e = NULL;
assert( be != NULL );
assert( slapMode & SLAP_TOOL_MODE );
assert( text != NULL );
assert( text->bv_val != NULL );
assert( text->bv_val[0] == '\0' ); /* overconservative? */
assert ( ndn != NULL );
assert ( ndn->bv_val != NULL );
Debug( LDAP_DEBUG_TRACE,
"=> wt_tool_entry_delete( %s )\n",
ndn->bv_val );
op.o_hdr = &ohdr;
op.o_bd = be;
op.o_tmpmemctx = NULL;
op.o_tmpmfuncs = &ch_mfuncs;
/* get entry */
rc = wt_dn2entry(op.o_bd, wc, ndn, &e);
switch( rc ) {
case 0:
break;
case WT_NOTFOUND:
Debug( LDAP_DEBUG_ARGS,
"<== wt_tool_entry_delete: no such object %s\n",
ndn->bv_val);
goto done;
default:
Debug( LDAP_DEBUG_ANY,
"wt_tool_entry_delete: error at wt_dn2entry() rc=%d\n",
rc );
goto done;
}
rc = wt_dn2id_has_children( &op, wc, e->e_id );
if( rc != WT_NOTFOUND ) {
/* subordinate objects must be deleted first */
rc = -1;
goto done;
}
rc = wc->session->begin_transaction(wc->session, NULL);
if( rc ){
Debug( LDAP_DEBUG_ANY,
"wt_tool_entry_delete: begin_transaction failed: %s (%d)\n",
wiredtiger_strerror(rc), rc );
goto done;
}
/* delete from dn2id */
rc = wt_dn2id_delete( &op, wc, &e->e_nname);
if ( rc ) {
Debug( LDAP_DEBUG_TRACE,
"<== wt_tool_entry_delete: dn2id failed: %s (%d)\n",
wiredtiger_strerror(rc), rc );
wc->session->rollback_transaction(wc->session, NULL);
goto done;
}
/* delete indices for old attributes */
rc = wt_index_entry_del( &op, wc, e );
if ( rc ) {
Debug( LDAP_DEBUG_TRACE,
"<== wt_tool_entry_delete: index delete failed: %s (%d)\n",
wiredtiger_strerror(rc), rc );
wc->session->rollback_transaction(wc->session, NULL);
goto done;
}
/* delete from id2entry */
rc = wt_id2entry_delete( &op, wc, e );
if ( rc ) {
Debug( LDAP_DEBUG_TRACE,
"<== wt_tool_entry_delete: id2entry failed: %s (%d)\n",
wiredtiger_strerror(rc), rc );
wc->session->rollback_transaction(wc->session, NULL);
goto done;
}
rc = wc->session->commit_transaction(wc->session, NULL);
if( rc != 0 ) {
snprintf( text->bv_val, text->bv_len,
"txn_commit failed: %s (%d)",
wiredtiger_strerror(rc), rc );
Debug( LDAP_DEBUG_ANY,
"=> wt_tool_entry_delete: %s\n",
text->bv_val );
goto done;
}
done:
/* free entry */
if( e != NULL ) {
wt_entry_return( e );
}
return rc;
}
/*
* Local variables:
* indent-tabs-mode: t

View file

@ -20,16 +20,19 @@ BUILD_MDB=@BUILD_MDB@
BUILD_SQL=@BUILD_SQL@
BUILD_SLAPD=@BUILD_SLAPD@
BUILD_BALANCER=@BUILD_BALANCER@
BUILD_WT=@BUILD_WT@
# test primary backends (default)
test tests:
@$(MAKE) mdb
@$(MAKE) lloadd
@$(MAKE) wt
# test all backends
alltests: tests
@$(MAKE) sql
@$(MAKE) ldif
@$(MAKE) wt
mdb test-mdb: mdb-$(BUILD_MDB)
mdb-no:
@ -51,6 +54,13 @@ ldif test-ldif: FORCE
@echo "Initiating LDAP tests for LDIF..."
@$(RUN) -b ldif all
wt test-wt: wt-$(BUILD_WT)
wt-no:
@echo "run configure with --enable-wt to run back-wt tests"
wt-yes wt-mod: FORCE
@$(RUN) -b wt all
lloadd test-lloadd: lloadd-$(BUILD_BALANCER)
lloadd-no:
@echo "run configure with --enable-balancer to run the Load Balancer tests"

View file

@ -6,6 +6,7 @@ verify basic functionality of the LDAP libraries and slapd.
To run SQL tests, define SLAPD_USE_SQL=<rdbms> and type
"make sql"; define SLAPD_USE_SQLWRITE=yes
to enable write tests as well.
To run WT tests, type "make wt".
To run regression tests, type "make regressions"
The test scripts depends on a number of tools commonly available on

View file

@ -38,6 +38,7 @@ AC_asyncmeta=asyncmeta@BUILD_ASYNCMETA@
AC_perl=perl@BUILD_PERL@
AC_relay=relay@BUILD_RELAY@
AC_sql=sql@BUILD_SQL@
AC_wt=@BUILD_WT@
# overlays
AC_accesslog=accesslog@BUILD_ACCESSLOG@
@ -188,6 +189,7 @@ INDEXDB=noindexdb MAINDB=nomaindb
case $BACKEND in
mdb) INDEXDB=indexdb MAINDB=maindb ;;
ndb) INDEXDB=indexdb ;;
wt) INDEXDB=indexdb ;;
esac
export BACKEND BACKENDTYPE INDEXDB MAINDB \

View file

@ -19,7 +19,12 @@ echo "running defines.sh"
if test $REFINT = refintno; then
echo "Referential Integrity overlay not available, test skipped"
exit 0
fi
fi
if test $BACKEND = wt ; then
echo "back-wt does not support subtree rename"
exit 0
fi
mkdir -p $TESTDIR $DBDIR1

View file

@ -16,6 +16,11 @@
echo "running defines.sh"
. $SRCDIR/scripts/defines.sh
if test $BACKEND = wt ; then
echo "back-wt does not support subtree rename"
exit 0
fi
mkdir -p $TESTDIR $DBDIR1
echo "Starting slapd on TCP/IP port $PORT1..."

View file

@ -20,12 +20,17 @@ echo "running defines.sh"
if test $MEMBEROF = memberofno; then
echo "Memberof overlay not available, test skipped"
exit 0
fi
fi
if test $REFINT = refintno; then
echo "Referential Integrity overlay not available, test skipped"
exit 0
fi
fi
if test $BACKEND = wt ; then
echo "back-wt does not support subtree rename"
exit 0
fi
mkdir -p $TESTDIR $DBDIR1 $TESTDIR/confdir