]> git.sur5r.net Git - openldap/commitdiff
ITS#7473 Add mdb_dn2id_walk() to walk subtree
authorHoward Chu <hyc@openldap.org>
Sat, 26 Jan 2013 20:32:46 +0000 (20:32 +0000)
committerHoward Chu <hyc@openldap.org>
Sun, 27 Jan 2013 00:19:38 +0000 (16:19 -0800)
Non-recursive tree walker.

servers/slapd/back-mdb/dn2id.c
servers/slapd/back-mdb/proto-mdb.h

index abbeee8c1b043bbea17bec4c76a3290bdb17890b..af003648af42abf76826590916927d34d9d82dbc 100644 (file)
@@ -756,3 +756,91 @@ mdb_idscopes(
        }
        return MDB_SUCCESS;
 }
+
+int
+mdb_dn2id_walk(
+       Operation *op,
+       IdScopes *isc
+)
+{
+       MDB_val key, data;
+       diskNode *d;
+       char *ptr;
+       int rc, n;
+       ID nsubs;
+
+       if ( !isc->numrdns ) {
+               key.mv_data = &isc->id;
+               key.mv_size = sizeof(ID);
+               rc = mdb_cursor_get( isc->mc, &key, &data, MDB_SET );
+               isc->scopes[0].mid = isc->id;
+               isc->numrdns++;
+               isc->nscope = 0;
+               /* skip base if not a subtree walk */
+               if ( op->ors_scope == LDAP_SCOPE_SUBTREE ||
+                       op->ors_scope == LDAP_SCOPE_BASE )
+                       return rc;
+       }
+       if ( op->ors_scope == LDAP_SCOPE_BASE )
+               return MDB_NOTFOUND;
+
+       for (;;) {
+               /* 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);
+                       d = data.mv_data;
+                       memcpy( &isc->id, ptr, sizeof(ID));
+
+                       /* If we're pushing down, see if there's any children to find */
+                       if ( isc->nscope ) {
+                               ptr += sizeof(ID);
+                               memcpy( &nsubs, ptr, sizeof(ID));
+                               /* No children, go to next sibling */
+                               if ( nsubs < 2 )
+                                       continue;
+                       }
+                       n = isc->numrdns;
+                       isc->scopes[n].mid = isc->id;
+                       n--;
+                       isc->nrdns[n].bv_len = ((d->nrdnlen[0] & 0x7f) << 8) | d->nrdnlen[1];
+                       isc->nrdns[n].bv_val = d->nrdn;
+                       isc->rdns[n].bv_val = d->nrdn+isc->nrdns[n].bv_len+1;
+                       isc->rdns[n].bv_len = data.mv_size - sizeof(diskNode) - isc->nrdns[n].bv_len - sizeof(ID);
+                       /* return this ID to caller */
+                       if ( !isc->nscope )
+                               break;
+
+                       /* push down to child */
+                       key.mv_data = &isc->id;
+                       mdb_cursor_get( isc->mc, &key, &data, MDB_SET );
+                       isc->nscope = 0;
+                       isc->numrdns++;
+                       continue;
+
+               } else if ( rc == MDB_NOTFOUND ) {
+                       if ( !isc->nscope && op->ors_scope != LDAP_SCOPE_ONELEVEL ) {
+                               /* reset to first dup */
+                               mdb_cursor_get( isc->mc, &key, NULL, MDB_GET_CURRENT );
+                               mdb_cursor_get( isc->mc, &key, &data, MDB_SET );
+                               isc->nscope = 1;
+                               continue;
+                       } else {
+                               isc->numrdns--;
+                               /* stack is empty? */
+                               if ( !isc->numrdns )
+                                       break;
+                               /* pop up to prev node */
+                               n = isc->numrdns - 1;
+                               key.mv_data = &isc->scopes[n].mid;
+                               key.mv_size = sizeof(ID);
+                               data.mv_data = isc->nrdns[n].bv_val - 2;
+                               mdb_cursor_get( isc->mc, &key, &data, MDB_GET_BOTH );
+                               continue;
+                       }
+               } else {
+                       break;
+               }
+       }
+       return rc;
+}
index ec677697139eee1e2ac2c2bdb2e5c8f83aec9486..a0d84da3ebc7b24a909989bdd397680aa7ea0545 100644 (file)
@@ -137,6 +137,10 @@ int mdb_idscopes(
        Operation *op,
        struct IdScopes *isc );
 
+int mdb_dn2id_walk(
+       Operation *op,
+       struct IdScopes *isc );
+
 MDB_cmp_func mdb_dup_compare;
 
 /*