summaryrefslogtreecommitdiffstats
path: root/servers/slapd/back-wt/dn2id.c
diff options
context:
space:
mode:
Diffstat (limited to 'servers/slapd/back-wt/dn2id.c')
-rw-r--r--servers/slapd/back-wt/dn2id.c453
1 files changed, 453 insertions, 0 deletions
diff --git a/servers/slapd/back-wt/dn2id.c b/servers/slapd/back-wt/dn2id.c
new file mode 100644
index 0000000..d8765ce
--- /dev/null
+++ b/servers/slapd/back-wt/dn2id.c
@@ -0,0 +1,453 @@
+/* OpenLDAP WiredTiger backend */
+/* $OpenLDAP$ */
+/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
+ *
+ * Copyright 2002-2022 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"
+#include "idl.h"
+
+static char *
+mkrevdn(struct berval src){
+ char *dst, *p;
+ char *rdn;
+ size_t rdn_len;
+
+ p = dst = ch_malloc(src.bv_len + 2);
+ while(src.bv_len){
+ rdn = ber_bvrchr( &src, ',' );
+ if (rdn) {
+ rdn_len = src.bv_len;
+ src.bv_len = rdn - src.bv_val;
+ rdn_len -= src.bv_len + 1;
+ rdn++;
+ }else{
+ /* first rdn */
+ rdn_len = src.bv_len;
+ rdn = src.bv_val;
+ src.bv_len = 0;
+ }
+ memcpy( p, rdn, rdn_len );
+ p += rdn_len;
+ *p++ = ',';
+ }
+ *p = '\0';
+ return dst;
+}
+
+int
+wt_dn2id_add(
+ Operation *op,
+ wt_ctx *wc,
+ ID pid,
+ Entry *e)
+{
+ struct wt_info *wi = (struct wt_info *) op->o_bd->be_private;
+ int rc;
+ 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",
+ e->e_id, e->e_ndn );
+ assert( e->e_id != NOID );
+
+ /* make reverse dn */
+ revdn = mkrevdn(e->e_nname);
+
+ 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,
+ "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;
+}
+
+int
+wt_dn2id_delete(
+ Operation *op,
+ wt_ctx *wc,
+ struct berval *ndn)
+{
+ struct wt_info *wi = (struct wt_info *) op->o_bd->be_private;
+ int rc = 0;
+ 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 );
+
+ /* 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, revdn);
+ rc = cursor->remove(cursor);
+ if ( rc ) {
+ Debug( LDAP_DEBUG_ANY,
+ "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 );
+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_ctx *wc,
+ struct berval *ndn,
+ ID *id)
+{
+ 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 );
+
+ if ( ndn->bv_len == 0 ) {
+ *id = 0;
+ 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);
+ rc = cursor->search(cursor);
+ switch( rc ){
+ case 0:
+ break;
+ case WT_NOTFOUND:
+ goto done;
+ default:
+ Debug( LDAP_DEBUG_ANY,
+ "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,
+ "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",
+ wiredtiger_strerror(rc), rc );
+ } else {
+ Debug( LDAP_DEBUG_TRACE, "<= wt_dn2id: got id=0x%lx\n",
+ *id );
+ }
+
+ return rc;
+}
+
+int
+wt_dn2id_has_children(
+ Operation *op,
+ wt_ctx *wc,
+ ID id )
+{
+ WT_SESSION *session = wc->session;
+ WT_CURSOR *cursor = wc->index_pid;
+ int rc;
+ uint64_t key = id;
+
+ 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_db(
+ Operation *op,
+ wt_ctx *wc,
+ struct berval *ndn,
+ Entry *e,
+ ID *ids,
+ ID *stack)
+{
+ WT_SESSION *session = wc->session;
+ WT_CURSOR *cursor = wc->dn2id;
+ int rc;
+ char *revdn = NULL;
+ size_t revdn_len;
+ char *key;
+ ID id, pid;
+
+ Debug( LDAP_DEBUG_TRACE,
+ "=> wt_dn2idl(\"%s\")\n",
+ ndn->bv_val );
+
+ revdn = mkrevdn(*ndn);
+ revdn_len = strlen(revdn);
+
+ if ( !cursor ) {
+ rc = session->open_cursor(session, WT_TABLE_DN2ID"(id, pid)",
+ NULL, NULL, &cursor);
+ if( rc ){
+ Debug( LDAP_DEBUG_ANY,
+ "wt_dn2idl: cursor open failed: %s (%d)\n",
+ wiredtiger_strerror(rc), rc );
+ goto done;
+ }
+ wc->dn2id = cursor;
+ }
+ cursor->set_key(cursor, revdn);
+ rc = cursor->search(cursor);
+ if( rc ){
+ Debug( LDAP_DEBUG_ANY,
+ "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,
+ "wt_dn2idl: get_key failed: %s (%d)\n",
+ wiredtiger_strerror(rc), rc );
+ goto done;
+ }
+ rc = cursor->get_value(cursor, &id, &pid);
+ if( rc ){
+ Debug( LDAP_DEBUG_ANY,
+ "wt_dn2id: get_value failed: %s (%d)\n",
+ wiredtiger_strerror(rc), rc );
+ goto done;
+ }
+
+ if( strncmp(revdn, key, revdn_len) ){
+ 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);
+
+ if (rc == WT_NOTFOUND ) {
+ 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;
+}
+
+int
+wt_dn2idl(
+ Operation *op,
+ wt_ctx *wc,
+ struct berval *ndn,
+ Entry *e,
+ ID *ids,
+ ID *stack)
+{
+ struct wt_info *wi = (struct wt_info *) op->o_bd->be_private;
+ int rc;
+
+ Debug( LDAP_DEBUG_TRACE,
+ "=> wt_dn2idl(\"%s\")\n", ndn->bv_val );
+
+ if(op->ors_scope != LDAP_SCOPE_ONELEVEL &&
+ be_issuffix( op->o_bd, &e->e_nname )){
+ WT_IDL_ALL(wi, ids);
+ return 0;
+ }
+
+ if (wi->wi_flags & WT_USE_IDLCACHE) {
+ rc = wt_idlcache_get(wc, ndn, op->ors_scope, ids);
+ if (rc == 0) {
+ /* cache hit */
+ return rc;
+ }
+ /* cache miss */
+ }
+
+ if ( wi->wi_flags & WT_USE_IDLCACHE ) {
+ wt_idlcache_begin(wc, ndn, op->ors_scope);
+ }
+ rc = wt_dn2idl_db(op, wc, ndn, e, ids, stack);
+ if ( rc == 0 && wi->wi_flags & WT_USE_IDLCACHE ) {
+ wt_idlcache_set(wc, ndn, op->ors_scope, ids);
+ }
+
+ return rc;
+}
+
+/*
+ * Local variables:
+ * indent-tabs-mode: t
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ */