]> git.ipfire.org Git - thirdparty/openldap.git/commitdiff
ITS#9463 cumulative fix for back-wt
authorHAMANO Tsukasa <hamano@osstech.co.jp>
Wed, 10 Feb 2021 13:56:09 +0000 (22:56 +0900)
committerQuanah Gibson-Mount <quanah@openldap.org>
Sat, 7 Aug 2021 19:27:43 +0000 (19:27 +0000)
- 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

34 files changed:
doc/man/man5/slapd-wt.5
servers/slapd/back-wt/Makefile.in
servers/slapd/back-wt/add.c
servers/slapd/back-wt/attr.c
servers/slapd/back-wt/back-wt.h
servers/slapd/back-wt/bind.c
servers/slapd/back-wt/cache.c [new file with mode: 0644]
servers/slapd/back-wt/compare.c
servers/slapd/back-wt/config.c
servers/slapd/back-wt/ctx.c
servers/slapd/back-wt/delete.c
servers/slapd/back-wt/dn2entry.c
servers/slapd/back-wt/dn2id.c
servers/slapd/back-wt/extended.c [new file with mode: 0644]
servers/slapd/back-wt/filterindex.c
servers/slapd/back-wt/id2entry.c
servers/slapd/back-wt/idl.c
servers/slapd/back-wt/idl.h
servers/slapd/back-wt/index.c
servers/slapd/back-wt/init.c
servers/slapd/back-wt/key.c
servers/slapd/back-wt/modify.c
servers/slapd/back-wt/modrdn.c [new file with mode: 0644]
servers/slapd/back-wt/nextid.c
servers/slapd/back-wt/operational.c
servers/slapd/back-wt/proto-wt.h
servers/slapd/back-wt/search.c
servers/slapd/back-wt/tools.c
tests/Makefile.in
tests/README
tests/run.in
tests/scripts/test023-refint
tests/scripts/test040-subtree-rename
tests/scripts/test057-memberof-refint

index d820f2cb97d8bf7990f78795263f281fb30c525a..d207374ff7dd35f995dfb13ec721372adc96abb5 100644 (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
index 4f1f33bcc2dc853b28b8d3b30136834e4cf7c74a..3f7e2b761e4757feab35a09b22d4e25b2b90e421 100644 (file)
 ## <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
index 5b9e83da3ea4e8d47e9e5120623218b897a1f10f..5613be2befda47e37c304734f9e7f9a95ef6c0b0 100644 (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 );
index 3aac12ff5e7d1723f905accdb9870e38d275978d..58a5e1570175068caa872f89832905f9ebc20bc7 100644 (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
index 87ee7357e5638e1cba7711a3e67a8d8110e2814c..121463afb31544cbadf8ffca8c9177023d393370 100644 (file)
 /* 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.) */
index c3908a161c5fd0badc9d2dbc6d79b3e2c8a3d96d..5c283f27bcf584e9961252240eabdb09769774ed 100644 (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 );
diff --git a/servers/slapd/back-wt/cache.c b/servers/slapd/back-wt/cache.c
new file mode 100644 (file)
index 0000000..eeced86
--- /dev/null
@@ -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:
+ */
index 1d13af7406d5036cf54f5e89e4112725b55c030f..d34bf68075a0684802d33a35e5c5216b38f5ee22 100644 (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;
index ed8ef395c00d590a241015d9df5c2b71eb6cda6c..79442ea3c28cb950f5ca841380bda48eda600c2f 100644 (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;
 }
index 6f09801d1e55b23773e432e3e1786dea9b45ba18..fa91cff2e81780315e5cc6ab186806434f3a75a0 100644 (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
index 20f06b2f1543c5b111f420b8a39137f05518174d..5a9e1b3ff6194435570f94cae749088e7ebe424f 100644 (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 );
-
-               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,
+                          "<== 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 );
+
+               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;
index c180e44596947f923d36d00537d457556f84adb9..6e6e08a02be75f06c283be0e6f9e8f45db01a7e4 100644 (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
index 5251203a0ce2c61966114d75b79240c507a405ef..58d98d9866993d4364eb2985c2028bef4c088aa0 100644 (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( rc ){
-               Debug( LDAP_DEBUG_ANY,
-                          LDAP_XSTRING(wt_dn2idl)
-                          ": cursor open failed: %s (%d)\n",
-                          wiredtiger_strerror(rc), rc );
-               goto done;
+
+       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_near(cursor, &exact);
+       rc = cursor->search(cursor);
        if( rc ){
                Debug( LDAP_DEBUG_ANY,
-                          LDAP_XSTRING(wt_dn2idl)
-                          ": search failed: %s (%d)\n",
+                          "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;
                }
-
-               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",
+                                  "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( strncmp(revdn, key, revdn_len) ){
+                       break;
+               }
+
+               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;
        }
+#endif
        return rc;
 }
 
-#if 0
 int
-wt_dn2id(
+wt_dn2idl(
        Operation *op,
-       WT_SESSION *session,
-    struct berval *dn,
-    ID *id)
+       wt_ctx *wc,
+       struct berval *ndn,
+       Entry *e,
+       ID *ids,
+       ID *stack)
 {
-       struct wt_info *wi = (struct wy_info *) op->o_bd->be_private;
-       WT_CURSOR *cursor = NULL;
+       struct wt_info *wi = (struct wt_info *) op->o_bd->be_private;
        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;
+       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;
        }
-       cursor->set_key(cursor, dn->bv_val);
-       rc = cursor->search(cursor);
-       if( !rc ){
-               cursor->get_key(cursor, &id);
+
+       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);
        }
-       cursor->close(cursor);
+
        return rc;
 }
-#endif
 
 /*
  * Local variables:
diff --git a/servers/slapd/back-wt/extended.c b/servers/slapd/back-wt/extended.c
new file mode 100644 (file)
index 0000000..306c34e
--- /dev/null
@@ -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:
+ */
index d2cdbc8346b51d8e3e120af18f23d991a54a13e8..a9d95f6b312123c8d265cc561530df114827294d 100644 (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;
 }
 
 /*
index 4240ac90a9337a049b9dfb97b1febf2e081bc30d..0fda2a9fb8f1a31f7bb70219e337547e79f63f61 100644 (file)
 
 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;
 }
 
 /*
index db83f1b33e939431acf40d9a57004949b5e2dd4b..0004ae63dea743ef82d81dafda9eea20a7557f9b 100644 (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;
index e8eb853dc178f4b30df5ce00bf4fa7347e406e0b..bcaf62cd5735ebfa33c702808b8d321e9b1f2f0b 100644 (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
index 06624591d3cf51b1c8ad39b5a06484fd38bff007..e5365fe1c518d104b627b8bce2a13441eed1d105 100644 (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
index 015d8566a97683e18113ed48a84900f33199d9c5..ba828bf109378ab11ce582d9a2c2b8b06f8a8414 100644 (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,
+                          "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,
-                          LDAP_XSTRING(wt_db_open) ": database \"%s\": "
-                          "cannot create revdn index: \"%s\"\n",
+                          "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;
index 4b5fd8d1845900e16040322d6ca68cf6a0c056b9..eb931917e5fbef4247448fe556619acdc9cb6bbd 100644 (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;
        }
 
index 3fa687a4732fb26ab15cdcf70754a6bf466e1f25..12bfd03e09352c1070545039a9ece19fded21175 100644 (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,49 +588,65 @@ 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";
-               }
+       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);
+               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;
+       default:
+               Debug( LDAP_DEBUG_ANY, "wt_modify: id2entry update failed (%d)\n",
+                          rs->sr_err);
+               rs->sr_err = LDAP_OTHER;
+               rs->sr_text = "entry update failed";
                goto return_results;
        }
 
+       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_modify: 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 ) {
-               wc->session->rollback_transaction(wc->session, NULL);
                rs->sr_err = LDAP_X_NO_OPERATION;
                goto return_results;
        }
@@ -602,10 +655,10 @@ wt_modify( Operation *op, SlapReply *rs )
        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,
-                          "<== " LDAP_XSTRING(wt_modify)
-                          ": commit failed: %s (%d)\n",
+                          "<== wt_modify: commit failed: %s (%d)\n",
                           wiredtiger_strerror(rc), rc );
                rs->sr_err = LDAP_OTHER;
                rs->sr_text = "commit failed";
@@ -613,32 +666,13 @@ wt_modify( Operation *op, SlapReply *rs )
        }
 
        Debug( LDAP_DEBUG_TRACE,
-                  LDAP_XSTRING(wt_modify) ": updated%s id=%08lx dn=\"%s\"\n",
+                  "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++];
-                       ctrls[num_ctrls] = NULL;
-               }
-               if( slap_read_controls( op, rs, &dummy,
-                                                               &slap_post_read_bv, postread_ctrl ) )
-               {
-                       Debug( LDAP_DEBUG_TRACE,
-                                  "<=- " LDAP_XSTRING(wt_modify)
-                                  ": 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( num_ctrls ) rs->sr_ctrls = ctrls;
-
        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;
 }
 
diff --git a/servers/slapd/back-wt/modrdn.c b/servers/slapd/back-wt/modrdn.c
new file mode 100644 (file)
index 0000000..990d56c
--- /dev/null
@@ -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:
+ */
index e2ae082654aee4212c70a8d35a7dc094121aba51..be0d5f5ae84d51b37e71e663ba0a43c76629dcd7 100644 (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;
     }
index c5e843847185cdb5f60996b4ba45e227a54b7797..780f39ddcca0acedb337f183d0e4abced03e31f3 100644 (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;
        }
index a218b428ea00cdb65018135bef1215d2b08269b9..1d7c2824c37e1a904b343bcbb57dee6eb18f33f4 100644 (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
 
index 3d4e6d7e1418fd1cae0629db068450e45612c167..ddd77cdc591d46b4be3082842e2ef22c75b9dd30 100644 (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;
 }
 
index 846edc091ae4ad90a55d2a89048df7a272433ad3..63b63bef89e3bcc43b63918c46b73e03d14b3d25 100644 (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
index d4abff7f09ede26081697cb85c649c2874844d63..606229315d03370d20d7c89e5f7da6bce28f125c 100644 (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"
index a3b5d2f304cabd405f655c55013cbd7468369986..e7a8a921d676e2c77db7905101ac8264cf5b2aed 100644 (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
index 0afeca07b51238de0bfa2da885a39d26172c7ea7..8df8c4c238e77aec6c355f29ca06412779c5c871 100644 (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 \
index 61a6833dcc55431f243aeb232b980db7cab92ed5..dc1a1b4a1739ddce0549bbc540fe175149589164 100755 (executable)
@@ -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
 
index 98022348bb35cfa566faeb2e935fc8011c47493d..f250c40aad116e6f7940cdcb26957a3afca869b9 100755 (executable)
 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..."
index 6ad1bface58b23df02a8680dde980436fb612b10..c1e0eb58cd2a986109e443f63eced4e0acc38d1c 100755 (executable)
@@ -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