]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/back-mdb/dn2id.c
ITS#8203 more fixes for #8036/#7904.
[openldap] / servers / slapd / back-mdb / dn2id.c
index d630741ef1ac78f88c42a70f23e786063f58f18b..43b82ce076df4a317d8979e9ffcc2f06e99df637 100644 (file)
@@ -2,7 +2,7 @@
 /* $OpenLDAP$ */
 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
  *
- * Copyright 2000-2013 The OpenLDAP Foundation.
+ * Copyright 2000-2015 The OpenLDAP Foundation.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -165,7 +165,7 @@ mdb_dn2id_add(
                        rc = mdb_cursor_get( mcp, &key, &data, MDB_SET );
                        if ( !rc ) {
                                char *p2;
-                               ptr = data.mv_data + data.mv_size - sizeof( ID );
+                               ptr = (char *)data.mv_data + data.mv_size - sizeof( ID );
                                memcpy( &nid, ptr, sizeof( ID ));
                                /* Get parent's node under grandparent */
                                d = data.mv_data;
@@ -178,7 +178,7 @@ mdb_dn2id_add(
                                op->o_tmpfree( p2, op->o_tmpmemctx );
                                if ( !rc ) {
                                        /* Get parent's subtree count */
-                                       ptr = data.mv_data + data.mv_size - sizeof( ID );
+                                       ptr = (char *)data.mv_data + data.mv_size - sizeof( ID );
                                        memcpy( &subs, ptr, sizeof( ID ));
                                        subs += nsubs;
                                        p2 = op->o_tmpalloc( data.mv_size, op->o_tmpmemctx );
@@ -246,7 +246,7 @@ mdb_dn2id_delete(
                                char *p2;
                                diskNode *d;
                                int rlen;
-                               ptr = data.mv_data + data.mv_size - sizeof( ID );
+                               ptr = (char *)data.mv_data + data.mv_size - sizeof( ID );
                                memcpy( &nid, ptr, sizeof( ID ));
                                /* Get parent's node under grandparent */
                                d = data.mv_data;
@@ -259,7 +259,7 @@ mdb_dn2id_delete(
                                op->o_tmpfree( p2, op->o_tmpmemctx );
                                if ( !rc ) {
                                        /* Get parent's subtree count */
-                                       ptr = data.mv_data + data.mv_size - sizeof( ID );
+                                       ptr = (char *)data.mv_data + data.mv_size - sizeof( ID );
                                        memcpy( &subs, ptr, sizeof( ID ));
                                        subs -= nsubs;
                                        p2 = op->o_tmpalloc( data.mv_size, op->o_tmpmemctx );
@@ -346,7 +346,7 @@ mdb_dn2id(
                cursor = mc;
        } else {
                rc = mdb_cursor_open( txn, dbi, &cursor );
-               if ( rc ) return rc;
+               if ( rc ) goto done;
        }
 
        for (;;) {
@@ -399,7 +399,7 @@ mdb_dn2id(
        *id = nid; 
        /* return subtree count if requested */
        if ( !rc && nsubs ) {
-               ptr = data.mv_data + data.mv_size - sizeof(ID);
+               ptr = (char *)data.mv_data + data.mv_size - sizeof(ID);
                memcpy( nsubs, ptr, sizeof( ID ));
        }
        if ( !mc )
@@ -470,7 +470,7 @@ mdb_dn2sups(
        key.mv_size = sizeof(ID);
 
        rc = mdb_cursor_open( txn, dbi, &cursor );
-       if ( rc ) return rc;
+       if ( rc ) goto done;
 
        for (;;) {
                key.mv_data = &pid;
@@ -664,6 +664,11 @@ mdb_idscope(
                        ptr += data.mv_size - sizeof(ID);
                        memcpy( &id, ptr, sizeof(ID) );
                        if ( id == base ) {
+                               if ( res[0] >= MDB_IDL_DB_SIZE-1 ) {
+                                       /* too many aliases in scope. Fallback to range */
+                                       MDB_IDL_RANGE( res, MDB_IDL_FIRST( ids ), MDB_IDL_LAST( ids ));
+                                       goto leave;
+                               }
                                res[0]++;
                                res[res[0]] = ida;
                                copy = 0;
@@ -685,6 +690,7 @@ mdb_idscope(
        if (!MDB_IDL_IS_RANGE( ids ))
                ids[0] = idc;
 
+leave:
        mdb_cursor_close( cursor );
        return rc;
 }
@@ -699,7 +705,7 @@ mdb_idscopes(
        struct mdb_info *mdb = (struct mdb_info *) op->o_bd->be_private;
        MDB_dbi dbi = mdb->mi_dn2id;
        MDB_val         key, data;
-       ID id;
+       ID id, prev;
        ID2 id2;
        char    *ptr;
        int             rc = 0;
@@ -723,6 +729,7 @@ mdb_idscopes(
                return MDB_SUCCESS;
        }
 
+       isc->sctmp[0].mid = 0;
        while (id) {
                if ( !rc ) {
                        key.mv_data = &id;
@@ -742,16 +749,32 @@ mdb_idscopes(
                isc->numrdns++;
 
                if (!rc && id != isc->id) {
+                       /* remember our chain of parents */
                        id2.mid = id;
                        id2.mval = data;
-                       mdb_id2l_insert( isc->scopes, &id2 );
+                       mdb_id2l_insert( isc->sctmp, &id2 );
                }
                ptr = data.mv_data;
                ptr += data.mv_size - sizeof(ID);
+               prev = id;
                memcpy( &id, ptr, sizeof(ID) );
+               /* If we didn't advance, some parent is missing */
+               if ( id == prev )
+                       return MDB_NOTFOUND;
+
                x = mdb_id2l_search( isc->scopes, id );
                if ( x <= isc->scopes[0].mid && isc->scopes[x].mid == id ) {
                        if ( !isc->scopes[x].mval.mv_data ) {
+                               /* This node is in scope, add parent chain to scope */
+                               int i;
+                               for ( i = 1; i <= isc->sctmp[0].mid; i++ ) {
+                                       rc = mdb_id2l_insert( isc->scopes, &isc->sctmp[i] );
+                                       if ( rc )
+                                               break;
+                               }
+                               /* check id again since inserts may have changed its position */
+                               if ( isc->scopes[x].mid != id )
+                                       x = mdb_id2l_search( isc->scopes, id );
                                isc->nscope = x;
                                return MDB_SUCCESS;
                        }
@@ -764,6 +787,53 @@ mdb_idscopes(
        return MDB_SUCCESS;
 }
 
+/* See if ID is a child of any of the scopes,
+ * return MDB_KEYEXIST if so.
+ */
+int
+mdb_idscopechk(
+       Operation *op,
+       IdScopes *isc )
+{
+       struct mdb_info *mdb = (struct mdb_info *) op->o_bd->be_private;
+       MDB_val         key, data;
+       ID id, prev;
+       char    *ptr;
+       int             rc = 0;
+       unsigned int x;
+
+       key.mv_size = sizeof(ID);
+
+       if ( !isc->mc ) {
+               rc = mdb_cursor_open( isc->mt, mdb->mi_dn2id, &isc->mc );
+               if ( rc ) return rc;
+       }
+
+       id = isc->id;
+
+       while (id) {
+               if ( !rc ) {
+                       key.mv_data = &id;
+                       rc = mdb_cursor_get( isc->mc, &key, &data, MDB_SET );
+                       if ( rc )
+                               return rc;
+               }
+
+               ptr = data.mv_data;
+               ptr += data.mv_size - sizeof(ID);
+               prev = id;
+               memcpy( &id, ptr, sizeof(ID) );
+               /* If we didn't advance, some parent is missing */
+               if ( id == prev )
+                       return MDB_NOTFOUND;
+
+               x = mdb_id2l_search( isc->scopes, id );
+               if ( x <= isc->scopes[0].mid && isc->scopes[x].mid == id )
+                       return MDB_KEYEXIST;
+       }
+       return MDB_SUCCESS;
+}
+
 int
 mdb_dn2id_walk(
        Operation *op,
@@ -795,7 +865,7 @@ mdb_dn2id_walk(
                /* Get next sibling */
                rc = mdb_cursor_get( isc->mc, &key, &data, MDB_NEXT_DUP );
                if ( !rc ) {
-                       ptr = data.mv_data + data.mv_size - 2*sizeof(ID);
+                       ptr = (char *)data.mv_data + data.mv_size - 2*sizeof(ID);
                        d = data.mv_data;
                        memcpy( &isc->id, ptr, sizeof(ID));
 
@@ -852,3 +922,45 @@ mdb_dn2id_walk(
        }
        return rc;
 }
+
+/* restore the nrdn/rdn pointers after a txn reset */
+void mdb_dn2id_wrestore (
+       Operation *op,
+       IdScopes *isc
+)
+{
+       MDB_val key, data;
+       diskNode *d;
+       int rc, n, nrlen;
+       char *ptr;
+
+       /* We only need to restore up to the n-1th element,
+        * the nth element will be replaced anyway
+        */
+       key.mv_size = sizeof(ID);
+       for ( n=0; n<isc->numrdns-1; n++ ) {
+               key.mv_data = &isc->scopes[n+1].mid;
+               rc = mdb_cursor_get( isc->mc, &key, &data, MDB_SET );
+               if ( rc )
+                       continue;
+               /* we can't use this data directly since its nrlen
+                * is missing the high bit setting, so copy it and
+                * set it properly. we just copy enough to satisfy
+                * mdb_dup_compare.
+                */
+               d = data.mv_data;
+               nrlen = ((d->nrdnlen[0] & 0x7f) << 8) | d->nrdnlen[1];
+               ptr = op->o_tmpalloc( nrlen+2, op->o_tmpmemctx );
+               memcpy( ptr, data.mv_data, nrlen+2 );
+               key.mv_data = &isc->scopes[n].mid;
+               data.mv_data = ptr;
+               data.mv_size = 1;
+               *ptr |= 0x80;
+               mdb_cursor_get( isc->mc, &key, &data, MDB_GET_BOTH );
+
+               /* now we're back to where we wanted to be */
+               d = data.mv_data;
+               isc->nrdns[n].bv_val = d->nrdn;
+               isc->rdns[n].bv_val = d->nrdn+isc->nrdns[n].bv_len+1;
+       }
+}