]> git.sur5r.net Git - openldap/commitdiff
ITS#4337 implement modrdn for back-config
authorHoward Chu <hyc@openldap.org>
Sun, 24 Dec 2006 00:56:37 +0000 (00:56 +0000)
committerHoward Chu <hyc@openldap.org>
Sun, 24 Dec 2006 00:56:37 +0000 (00:56 +0000)
servers/slapd/back-relay/config.c
servers/slapd/backend.c
servers/slapd/backglue.c
servers/slapd/backover.c
servers/slapd/bconfig.c
servers/slapd/modrdn.c
servers/slapd/overlays/pcache.c
servers/slapd/overlays/translucent.c
servers/slapd/proto-slap.h
servers/slapd/slapi/slapi_overlay.c

index b8f85830115a5883ff1840862c1cc422a80f933c..b11e37118c12e10fb678cc0ccf10c3ea50beac69 100644 (file)
@@ -114,7 +114,7 @@ relay_back_db_config(
                 * where the overlay is instantiated by moving
                 * around the "relay" directive, although this could
                 * make slapd.conf a bit confusing. */
-               if ( overlay_config( be, "rwm" ) ) {
+               if ( overlay_config( be, "rwm", -1, NULL ) ) {
                        Log2( LDAP_DEBUG_ANY, LDAP_LEVEL_ERR,
                                "%s: line %d: unable to install "
                                "rwm overlay "
index 24294b14e3cde1ffd2b1634091c2241b76e67897..3233f65e8fe44a12493a5c08a3ae6b1c38efca6f 100644 (file)
@@ -530,13 +530,48 @@ BackendInfo* backend_info(const char *type)
        return NULL;
 }
 
+void
+backend_db_insert(
+       BackendDB *be,
+       int idx
+)
+{
+       /* If idx < 0, just add to end of list */
+       if ( idx < 0 ) {
+               LDAP_STAILQ_INSERT_TAIL(&backendDB, be, be_next);
+       } else if ( idx == 0 ) {
+               LDAP_STAILQ_INSERT_HEAD(&backendDB, be, be_next);
+       } else {
+               int i;
+               BackendDB *b2;
+
+               b2 = LDAP_STAILQ_FIRST(&backendDB);
+               idx--;
+               for (i=0; i<idx; i++) {
+                       b2 = LDAP_STAILQ_NEXT(b2, be_next);
+               }
+               LDAP_STAILQ_INSERT_AFTER(&backendDB, b2, be, be_next);
+       }
+}
+
+void
+backend_db_move(
+       BackendDB *be,
+       int idx
+)
+{
+       LDAP_STAILQ_REMOVE(&backendDB, be, slap_backend_db, be_next);
+       backend_db_insert(be, idx);
+}
 
 BackendDB *
 backend_db_init(
     const char *type,
-       BackendDB *be )
+       BackendDB *b0,
+       int idx )
 {
        BackendInfo *bi = backend_info(type);
+       BackendDB *be = b0;
        int     rc = 0;
 
        if( bi == NULL ) {
@@ -549,8 +584,11 @@ backend_db_init(
         */
        if ( !be ) {
                be = ch_calloc( 1, sizeof(Backend) );
+               /* Just append */
+               if ( idx >= nbackends )
+                       idx = -1;
                nbackends++;
-               LDAP_STAILQ_INSERT_TAIL(&backendDB, be, be_next);
+               backend_db_insert( be, idx );
        }
 
        be->bd_info = bi;
@@ -574,11 +612,16 @@ backend_db_init(
 
        if ( rc != 0 ) {
                fprintf( stderr, "database init failed (%s)\n", type );
-               nbackends--;
-               return NULL;
+               /* If we created and linked this be, remove it and free it */
+               if ( !b0 ) {
+                       LDAP_STAILQ_REMOVE(&backendDB, be, slap_backend_db, be_next);
+                       ch_free( be );
+                       be = NULL;
+                       nbackends--;
+               }
+       } else {
+               bi->bi_nDB++;
        }
-
-       bi->bi_nDB++;
        return( be );
 }
 
index d9bee99bd8f427f292ca4e00d448133c371d328c..6d516d3e5a05e851a2c715316921488bfe6a0791 100644 (file)
@@ -956,7 +956,7 @@ glue_sub_attach()
 
                        /* If it's not already configured, set up the overlay */
                        if ( !SLAP_GLUE_INSTANCE( be )) {
-                               rc = overlay_config( be, glue.on_bi.bi_type );
+                               rc = overlay_config( be, glue.on_bi.bi_type, -1, NULL );
                                if ( rc )
                                        break;
                        }
index 95673a88bce150cfe77d16f0548513e92ca2c4aa..9a7b4df76114a88412287ed5cc529d32c0f85138 100644 (file)
@@ -942,14 +942,77 @@ overlay_destroy_one( BackendDB *be, slap_overinst *on )
        }
 }
 
+void
+overlay_insert( BackendDB *be, slap_overinst *on2, slap_overinst ***prev,
+       int idx )
+{
+       slap_overinfo *oi = (slap_overinfo *)be->bd_info;
+
+       if ( idx == -1 ) {
+               on2->on_next = oi->oi_list;
+               oi->oi_list = on2;
+       } else {
+               int i;
+               slap_overinst *on, *otmp1 = NULL, *otmp2;
+
+               /* Since the list is in reverse order and is singly linked,
+                * we reverse it to find the idx insertion point. Adding
+                * on overlay at a specific point should be a pretty
+                * infrequent occurrence.
+                */
+               for ( on = oi->oi_list; on; on=otmp2 ) {
+                       otmp2 = on->on_next;
+                       on->on_next = otmp1;
+                       otmp1 = on;
+               }
+               oi->oi_list = NULL;
+               /* advance to insertion point */
+               for ( i=0, on = otmp1; i<idx; i++ ) {
+                       otmp1 = on->on_next;
+                       on->on_next = oi->oi_list;
+                       oi->oi_list = on;
+               }
+               /* insert */
+               on2->on_next = oi->oi_list;
+               oi->oi_list = on2;
+               if ( otmp1 ) {
+                       *prev = &otmp1->on_next;
+                       /* replace remainder of list */
+                       for ( on=otmp1; on; on=otmp1 ) {
+                               otmp1 = on->on_next;
+                               on->on_next = oi->oi_list;
+                               oi->oi_list = on;
+                       }
+               }
+       }
+}
+
+void
+overlay_move( BackendDB *be, slap_overinst *on, int idx )
+{
+       slap_overinfo *oi = (slap_overinfo *)be->bd_info;
+       slap_overinst **onp;
+
+       for (onp = &oi->oi_list; *onp; onp= &(*onp)->on_next) {
+               if ( *onp == on ) {
+                       *onp = on->on_next;
+                       break;
+               }
+       }
+       overlay_insert( be, on, &onp, idx );
+}
+
 /* add an overlay to a particular backend. */
 int
-overlay_config( BackendDB *be, const char *ov )
+overlay_config( BackendDB *be, const char *ov, int idx, BackendInfo **res )
 {
-       slap_overinst *on = NULL, *on2 = NULL;
+       slap_overinst *on = NULL, *on2 = NULL, **prev;
        slap_overinfo *oi = NULL;
        BackendInfo *bi = NULL;
 
+       if ( res )
+               *res = NULL;
+
        on = overlay_find( ov );
        if ( !on ) {
                Debug( LDAP_DEBUG_ANY, "overlay \"%s\" not found\n", ov, 0, 0 );
@@ -1049,28 +1112,44 @@ overlay_config( BackendDB *be, const char *ov )
                oi = be->bd_info->bi_private;
        }
 
-       /* Insert new overlay on head of list. Overlays are executed
-        * in reverse of config order...
+       /* Insert new overlay into list. By default overlays are
+        * added to head of list and executed in LIFO order.
         */
        on2 = ch_calloc( 1, sizeof(slap_overinst) );
        *on2 = *on;
        on2->on_info = oi;
-       on2->on_next = oi->oi_list;
-       oi->oi_list = on2;
+
+       prev = &oi->oi_list;
+       /* Do we need to find the insertion point? */
+       if ( idx >= 0 ) {
+               int i;
+
+               /* count current overlays */
+               for ( i=0, on=oi->oi_list; on; on=on->on_next, i++ );
+
+               /* are we just appending a new one? */
+               if ( idx >= i )
+                       idx = -1;
+       }
+       overlay_insert( be, on2, &prev, idx );
 
        /* Any initialization needed? */
-       if ( on->on_bi.bi_db_init ) {
+       if ( on2->on_bi.bi_db_init ) {
                int rc;
                be->bd_info = (BackendInfo *)on2;
                rc = on2->on_bi.bi_db_init( be );
                be->bd_info = (BackendInfo *)oi;
                if ( rc ) {
-                       oi->oi_list = on2->on_next;
+                       *prev = on2->on_next;
                        ch_free( on2 );
+                       on2 = NULL;
                        return rc;
                }
        }
 
+       if ( res )
+               *res = &on2->on_bi;
+
        return 0;
 }
 
index 6efd2d2df6aeacb80cdbee6ba6c32f8ddfa3cd7f..a51dd04f2aa03b933f1c818f696e00414d05b729 100644 (file)
@@ -1228,7 +1228,7 @@ config_generic(ConfigArgs *c) {
                        } else if ( !strcasecmp( c->argv[1], "frontend" )) {
                                c->be = frontendDB;
                        } else {
-                               c->be = backend_db_init(c->argv[1], NULL);
+                               c->be = backend_db_init(c->argv[1], NULL, c->valx);
                                if ( !c->be ) {
                                        snprintf( c->msg, sizeof( c->msg ), "<%s> failed init", c->argv[0] );
                                        Debug(LDAP_DEBUG_ANY, "%s: %s (%s)!\n",
@@ -1934,26 +1934,21 @@ config_timelimit(ConfigArgs *c) {
 
 static int
 config_overlay(ConfigArgs *c) {
-       slap_overinfo *oi;
        if (c->op == SLAP_CONFIG_EMIT) {
                return 1;
        } else if ( c->op == LDAP_MOD_DELETE ) {
                assert(0);
        }
-       if(c->argv[1][0] == '-' && overlay_config(c->be, &c->argv[1][1])) {
+       if(c->argv[1][0] == '-' && overlay_config(c->be, &c->argv[1][1],
+               c->valx, &c->bi)) {
                /* log error */
                Debug( LDAP_DEBUG_ANY,
                        "%s: (optional) %s overlay \"%s\" configuration failed.\n",
                        c->log, c->be == frontendDB ? "global " : "", &c->argv[1][1]);
                return 1;
-       } else if(overlay_config(c->be, c->argv[1])) {
+       } else if(overlay_config(c->be, c->argv[1], c->valx, &c->bi)) {
                return(1);
        }
-       /* Setup context for subsequent config directives.
-        * The newly added overlay is at the head of the list.
-        */
-       oi = (slap_overinfo *)c->be->bd_info;
-       c->bi = &oi->oi_list->on_bi;
        return(0);
 }
 
@@ -3218,8 +3213,11 @@ config_ldif_resp( Operation *op, SlapReply *rs )
                                                sc->cfb->cb_root, sc->ca, &rdn, &CFOC_DATABASE,
                                                sc->ca->be->be_cf_ocs );
                                        op->o_noop = i;
+                                       sc->got_frontend++;
+                               } else {
+                                       sc->got_frontend++;
+                                       goto ok;
                                }
-                               sc->got_frontend++;
                        }
                }
                /* Does the configDB exist? */
@@ -3246,6 +3244,7 @@ config_ldif_resp( Operation *op, SlapReply *rs )
                        sc->got_config++;
                }
 
+ok:
                rs->sr_err = config_add_internal( sc->cfb, rs->sr_entry, sc->ca, NULL, NULL, NULL );
                if ( rs->sr_err != LDAP_SUCCESS ) {
                        Debug( LDAP_DEBUG_ANY, "config error processing %s: %s\n",
@@ -3285,7 +3284,7 @@ config_setup_ldif( BackendDB *be, const char *dir, int readit ) {
        if ( !cfb->cb_db.bd_info )
                return 0;       /* FIXME: eventually this will be a fatal error */
 
-       if ( backend_db_init( "ldif", &cfb->cb_db ) == NULL )
+       if ( backend_db_init( "ldif", &cfb->cb_db, -1 ) == NULL )
                return 1;
 
        cfb->cb_db.be_suffix = be->be_suffix;
@@ -3421,7 +3420,7 @@ read_config(const char *fname, const char *dir) {
        int rc;
 
        /* Setup the config backend */
-       be = backend_db_init( "config", NULL );
+       be = backend_db_init( "config", NULL, 0 );
        if ( !be )
                return 1;
 
@@ -3654,12 +3653,177 @@ check_vals( ConfigTable *ct, ConfigArgs *ca, void *ptr, int isAttr )
        return rc;
 }
 
+static int
+config_rename_attr( SlapReply *rs, Entry *e, struct berval *rdn,
+       Attribute **at )
+{
+       struct berval rtype, rval;
+       Attribute *a;
+       AttributeDescription *ad = NULL;
+
+       dnRdn( &e->e_name, rdn );
+       rval.bv_val = strchr(rdn->bv_val, '=' ) + 1;
+       rval.bv_len = rdn->bv_len - (rval.bv_val - rdn->bv_val);
+       rtype.bv_val = rdn->bv_val;
+       rtype.bv_len = rval.bv_val - rtype.bv_val - 1;
+
+       /* Find attr */
+       slap_bv2ad( &rtype, &ad, &rs->sr_text );
+       a = attr_find( e->e_attrs, ad );
+       if (!a ) return LDAP_NAMING_VIOLATION;
+       *at = a;
+
+       return 0;
+}
+
+static void
+config_rename_kids( CfEntryInfo *ce )
+{
+       CfEntryInfo *ce2;
+       struct berval rdn, nrdn;
+
+       for (ce2 = ce->ce_kids; ce2; ce2 = ce2->ce_sibs) {
+               dnRdn ( &ce2->ce_entry->e_name, &rdn );
+               dnRdn ( &ce2->ce_entry->e_nname, &nrdn );
+               free( ce2->ce_entry->e_name.bv_val );
+               free( ce2->ce_entry->e_nname.bv_val );
+               build_new_dn( &ce2->ce_entry->e_name, &ce->ce_entry->e_name,
+                       &rdn, NULL );
+               build_new_dn( &ce2->ce_entry->e_nname, &ce->ce_entry->e_nname,
+                       &nrdn, NULL );
+               config_rename_kids( ce2 );
+       }
+}
+
+static int
+config_rename_one( Operation *op, SlapReply *rs, Entry *e,
+       CfEntryInfo *parent, Attribute *a, struct berval *newrdn,
+       struct berval *nnewrdn, int use_ldif )
+{
+       char *ptr1;
+       int rc = 0;
+       struct berval odn, ondn;
+
+       odn = e->e_name;
+       ondn = e->e_nname;
+       build_new_dn( &e->e_name, &parent->ce_entry->e_name, newrdn, NULL );
+       build_new_dn( &e->e_nname, &parent->ce_entry->e_nname, nnewrdn, NULL );
+
+       /* Replace attr */
+       free( a->a_vals[0].bv_val );
+       ptr1 = strchr( newrdn->bv_val, '=' ) + 1;
+       a->a_vals[0].bv_len = newrdn->bv_len - (ptr1 - newrdn->bv_val);
+       a->a_vals[0].bv_val = ch_malloc( a->a_vals[0].bv_len + 1 );
+       strcpy( a->a_vals[0].bv_val, ptr1 );
+
+       if ( a->a_nvals != a->a_vals ) {
+               free( a->a_nvals[0].bv_val );
+               ptr1 = strchr( nnewrdn->bv_val, '=' ) + 1;
+               a->a_nvals[0].bv_len = nnewrdn->bv_len - (ptr1 - nnewrdn->bv_val);
+               a->a_nvals[0].bv_val = ch_malloc( a->a_nvals[0].bv_len + 1 );
+               strcpy( a->a_nvals[0].bv_val, ptr1 );
+       }
+       if ( use_ldif ) {
+               CfBackInfo *cfb = (CfBackInfo *)op->o_bd->be_private;
+               BackendDB *be = op->o_bd;
+               slap_callback sc = { NULL, slap_null_cb, NULL, NULL };
+               struct berval dn, ndn, xdn, xndn;
+
+               op->o_bd = &cfb->cb_db;
+
+               /* Save current rootdn; use the underlying DB's rootdn */
+               dn = op->o_dn;
+               ndn = op->o_ndn;
+               xdn = op->o_req_dn;
+               xndn = op->o_req_ndn;
+               op->o_dn = op->o_bd->be_rootdn;
+               op->o_ndn = op->o_bd->be_rootndn;
+               op->o_req_dn = odn;
+               op->o_req_ndn = ondn;
+
+               sc.sc_next = op->o_callback;
+               op->o_callback = &sc;
+               op->orr_newrdn = *newrdn;
+               op->orr_nnewrdn = *nnewrdn;
+               op->orr_deleteoldrdn = 1;
+               op->orr_modlist = NULL;
+               slap_modrdn2mods( op, rs );
+               rc = op->o_bd->be_modrdn( op, rs );
+               slap_mods_free( op->orr_modlist, 1 );
+
+               op->o_bd = be;
+               op->o_callback = sc.sc_next;
+               op->o_dn = dn;
+               op->o_ndn = ndn;
+               op->o_req_dn = xdn;
+               op->o_req_ndn = xndn;
+       }
+       free( odn.bv_val );
+       free( ondn.bv_val );
+       if ( e->e_private )
+               config_rename_kids( e->e_private );
+       return rc;
+}
+
+static int
+config_renumber_one( Operation *op, SlapReply *rs, CfEntryInfo *parent, 
+       Entry *e, int idx, int tailindex, int use_ldif )
+{
+       struct berval ival, newrdn, nnewrdn;
+       struct berval rdn;
+       Attribute *a;
+       char ibuf[32], *ptr1, *ptr2 = NULL;
+       int rc = 0;
+
+       rc = config_rename_attr( rs, e, &rdn, &a );
+       if ( rc ) return rc;
+
+       ival.bv_val = ibuf;
+       ival.bv_len = snprintf( ibuf, sizeof( ibuf ), SLAP_X_ORDERED_FMT, idx );
+       if ( ival.bv_len >= sizeof( ibuf ) ) {
+               return LDAP_NAMING_VIOLATION;
+       }
+       
+       newrdn.bv_len = rdn.bv_len + ival.bv_len;
+       newrdn.bv_val = ch_malloc( newrdn.bv_len+1 );
+
+       if ( tailindex ) {
+               ptr1 = lutil_strncopy( newrdn.bv_val, rdn.bv_val, rdn.bv_len );
+               ptr1 = lutil_strcopy( ptr1, ival.bv_val );
+       } else {
+               int xlen;
+               ptr2 = ber_bvchr( &rdn, '}' );
+               if ( ptr2 ) {
+                       ptr2++;
+               } else {
+                       ptr2 = rdn.bv_val + a->a_desc->ad_cname.bv_len + 1;
+               }
+               xlen = rdn.bv_len - (ptr2 - rdn.bv_val);
+               ptr1 = lutil_strncopy( newrdn.bv_val, a->a_desc->ad_cname.bv_val,
+                       a->a_desc->ad_cname.bv_len );
+               *ptr1++ = '=';
+               ptr1 = lutil_strcopy( ptr1, ival.bv_val );
+               ptr1 = lutil_strncopy( ptr1, ptr2, xlen );
+               *ptr1 = '\0';
+       }
+
+       /* Do the equivalent of ModRDN */
+       /* Replace DN / NDN */
+       newrdn.bv_len = ptr1 - newrdn.bv_val;
+       rdnNormalize( 0, NULL, NULL, &newrdn, &nnewrdn, NULL );
+       rc = config_rename_one( op, rs, e, parent, a, &newrdn, &nnewrdn, use_ldif );
+
+       free( nnewrdn.bv_val );
+       free( newrdn.bv_val );
+       return rc;
+}
+
 static int
 check_name_index( CfEntryInfo *parent, ConfigType ce_type, Entry *e,
-       SlapReply *rs, int *renum )
+       SlapReply *rs, int *renum, int *ibase )
 {
        CfEntryInfo *ce;
-       int index = -1, gotindex = 0, nsibs;
+       int index = -1, gotindex = 0, nsibs, rc = 0;
        int renumber = 0, tailindex = 0;
        char *ptr1, *ptr2 = NULL;
        struct berval rdn;
@@ -3710,83 +3874,14 @@ check_name_index( CfEntryInfo *parent, ConfigType ce_type, Entry *e,
                                renumber = 1;
                        }
                }
+               /* just make index = nsibs */
                if ( !renumber ) {
-                       struct berval ival, newrdn, nnewrdn;
-                       struct berval rtype, rval;
-                       Attribute *a;
-                       AttributeDescription *ad = NULL;
-                       char ibuf[32];
-                       const char *text;
-
-                       rval.bv_val = strchr(rdn.bv_val, '=' ) + 1;
-                       rval.bv_len = rdn.bv_len - (rval.bv_val - rdn.bv_val);
-                       rtype.bv_val = rdn.bv_val;
-                       rtype.bv_len = rval.bv_val - rtype.bv_val - 1;
-
-                       /* Find attr */
-                       slap_bv2ad( &rtype, &ad, &text );
-                       a = attr_find( e->e_attrs, ad );
-                       if (!a ) return LDAP_NAMING_VIOLATION;
-
-                       ival.bv_val = ibuf;
-                       ival.bv_len = snprintf( ibuf, sizeof( ibuf ), SLAP_X_ORDERED_FMT, nsibs );
-                       if ( ival.bv_len >= sizeof( ibuf ) ) {
-                               return LDAP_NAMING_VIOLATION;
-                       }
-                       
-                       newrdn.bv_len = rdn.bv_len + ival.bv_len;
-                       newrdn.bv_val = ch_malloc( newrdn.bv_len+1 );
-
-                       if ( tailindex ) {
-                               ptr1 = lutil_strncopy( newrdn.bv_val, rdn.bv_val, rdn.bv_len );
-                               ptr1 = lutil_strcopy( ptr1, ival.bv_val );
-                       } else {
-                               int xlen;
-                               if ( !gotindex ) {
-                                       ptr2 = rval.bv_val;
-                                       xlen = rval.bv_len;
-                               } else {
-                                       xlen = rdn.bv_len - (ptr2 - rdn.bv_val);
-                               }
-                               ptr1 = lutil_strncopy( newrdn.bv_val, rtype.bv_val,
-                                       rtype.bv_len );
-                               *ptr1++ = '=';
-                               ptr1 = lutil_strcopy( ptr1, ival.bv_val );
-                               ptr1 = lutil_strncopy( ptr1, ptr2, xlen );
-                               *ptr1 = '\0';
-                       }
-
-                       /* Do the equivalent of ModRDN */
-                       /* Replace DN / NDN */
-                       newrdn.bv_len = ptr1 - newrdn.bv_val;
-                       rdnNormalize( 0, NULL, NULL, &newrdn, &nnewrdn, NULL );
-                       free( e->e_name.bv_val );
-                       build_new_dn( &e->e_name, &parent->ce_entry->e_name,
-                               &newrdn, NULL );
-                       free( e->e_nname.bv_val );
-                       build_new_dn( &e->e_nname, &parent->ce_entry->e_nname,
-                               &nnewrdn, NULL );
-
-                       /* Replace attr */
-                       free( a->a_vals[0].bv_val );
-                       ptr1 = strchr( newrdn.bv_val, '=' ) + 1;
-                       a->a_vals[0].bv_len = newrdn.bv_len - (ptr1 - newrdn.bv_val);
-                       a->a_vals[0].bv_val = ch_malloc( a->a_vals[0].bv_len + 1 );
-                       strcpy( a->a_vals[0].bv_val, ptr1 );
-
-                       if ( a->a_nvals != a->a_vals ) {
-                               free( a->a_nvals[0].bv_val );
-                               ptr1 = strchr( nnewrdn.bv_val, '=' ) + 1;
-                               a->a_nvals[0].bv_len = nnewrdn.bv_len - (ptr1 - nnewrdn.bv_val);
-                               a->a_nvals[0].bv_val = ch_malloc( a->a_nvals[0].bv_len + 1 );
-                               strcpy( a->a_nvals[0].bv_val, ptr1 );
-                       }
-                       free( nnewrdn.bv_val );
-                       free( newrdn.bv_val );
+                       rc = config_renumber_one( NULL, rs, parent, e, index, tailindex, 0 );
                }
        }
+       if ( ibase ) *ibase = index;
        if ( renum ) *renum = renumber;
-       return 0;
+       return rc;
 }
 
 static ConfigOCs **
@@ -3897,14 +3992,17 @@ config_add_internal( CfBackInfo *cfb, Entry *e, ConfigArgs *ca, SlapReply *rs,
        CfEntryInfo *ce, *last;
        ConfigOCs **colst;
        Attribute *a, *oc_at;
-       int i, nocs, rc = 0;
+       int i, ibase = -1, nocs, rc = 0;
        struct berval pdn;
        ConfigTable *ct;
        char *ptr;
 
-       /* Make sure parent exists and entry does not */
+       /* Make sure parent exists and entry does not. But allow
+        * Databases and Overlays to be inserted.
+        */
        ce = config_find_base( cfb->cb_root, &e->e_nname, &last );
-       if ( ce )
+       if ( ce && ce->ce_type != Cft_Database &&
+               ce->ce_type != Cft_Overlay )
                return LDAP_ALREADY_EXISTS;
 
        dnParent( &e->e_nname, &pdn );
@@ -3995,12 +4093,13 @@ config_add_internal( CfBackInfo *cfb, Entry *e, ConfigArgs *ca, SlapReply *rs,
         * but only the other types support auto-renumbering of siblings.
         */
        {
-               int renumber = renum ? *renum : 0;
-               rc = check_name_index( last, colst[0]->co_type, e, rs, renum );
+               rc = check_name_index( last, colst[0]->co_type, e, rs, renum,
+                       &ibase );
                if ( rc ) {
                        goto done;
                }
-               if ( renum && *renum && renumber == -1 ) {
+               if ( renum && *renum && colst[0]->co_type != Cft_Database &&
+                       colst[0]->co_type != Cft_Overlay ) {
                        snprintf( ca->msg, sizeof( ca->msg ),
                                "operation requires sibling renumbering" );
                        rc = LDAP_UNWILLING_TO_PERFORM;
@@ -4027,12 +4126,24 @@ config_add_internal( CfBackInfo *cfb, Entry *e, ConfigArgs *ca, SlapReply *rs,
                ct = config_find_table( colst, nocs, a->a_desc );
                if ( !ct ) continue;    /* user data? */
                for (i=0; a->a_vals[i].bv_val; i++) {
+                       char *iptr = NULL;
                        ca->line = a->a_vals[i].bv_val;
                        if ( a->a_desc->ad_type->sat_flags & SLAP_AT_ORDERED ) {
                                ptr = strchr( ca->line, '}' );
-                               if ( ptr ) ca->line = ptr+1;
+                               if ( ptr ) {
+                                       iptr = strchr( ca->line, '{' );
+                                       ca->line = ptr+1;
+                               }
+                       }
+                       if ( a->a_desc->ad_type->sat_flags & SLAP_AT_ORDERED_SIB ) {
+                               if ( iptr ) {
+                                       ca->valx = strtol( iptr+1, NULL, 0 );
+                               } else {
+                                       ca->valx = -1;
+                               }
+                       } else {
+                               ca->valx = i;
                        }
-                       ca->valx = i;
                        rc = config_parse_add( ct, ca, i );
                        if ( rc ) {
                                rc = LDAP_OTHER;
@@ -4063,6 +4174,7 @@ ok:
                }
        }
 
+       ca->valx = ibase;
        ce = ch_calloc( 1, sizeof(CfEntryInfo) );
        ce->ce_parent = last;
        ce->ce_entry = entry_dup( e );
@@ -4071,6 +4183,7 @@ ok:
        ce->ce_be = ca->be;
        ce->ce_bi = ca->bi;
        ce->ce_private = ca->private;
+       ca->ca_entry = ce->ce_entry;
        if ( !last ) {
                cfb->cb_root = ce;
        } else if ( last->ce_kids ) {
@@ -4098,6 +4211,76 @@ done:
        return rc;
 }
 
+#define        BIGTMP  10000
+static int
+config_rename_add( Operation *op, SlapReply *rs, CfEntryInfo *ce,
+       int base, int rebase, int max, int use_ldif )
+{
+       CfEntryInfo *ce2, *ce3, *cetmp = NULL, *cerem = NULL;
+       ConfigType etype = ce->ce_type;
+       int count = 0, rc = 0;
+
+       /* Reverse ce list */
+       for (ce2 = ce->ce_sibs;ce2;ce2 = ce3) {
+               if (ce2->ce_type != etype) {
+                       cerem = ce2;
+                       break;
+               }
+               ce3 = ce2->ce_sibs;
+               ce2->ce_sibs = cetmp;
+               cetmp = ce2;
+               count++;
+               if ( max && count >= max ) {
+                       cerem = ce3;
+                       break;
+               }
+       }
+
+       /* Move original to a temp name until increments are done */
+       if ( rebase ) {
+               ce->ce_entry->e_private = NULL;
+               rc = config_renumber_one( op, rs, ce->ce_parent, ce->ce_entry,
+                       base+BIGTMP, 0, use_ldif );
+               ce->ce_entry->e_private = ce;
+       }
+       /* start incrementing */
+       for (ce2=cetmp; ce2; ce2=ce3) {
+               ce3 = ce2->ce_sibs;
+               ce2->ce_sibs = cerem;
+               cerem = ce2;
+               if ( rc == 0 ) 
+                       rc = config_renumber_one( op, rs, ce2->ce_parent, ce2->ce_entry,
+                               count+base, 0, use_ldif );
+               count--;
+       }
+       if ( rebase )
+               rc = config_renumber_one( op, rs, ce->ce_parent, ce->ce_entry,
+                       base, 0, use_ldif );
+       return rc;
+}
+
+static int
+config_rename_del( Operation *op, SlapReply *rs, CfEntryInfo *ce,
+       CfEntryInfo *ce2, int old, int use_ldif )
+{
+       int count = 0;
+
+       /* Renumber original to a temp value */
+       ce->ce_entry->e_private = NULL;
+       config_renumber_one( op, rs, ce->ce_parent, ce->ce_entry,
+               old+BIGTMP, 0, use_ldif );
+       ce->ce_entry->e_private = ce;
+
+       /* start decrementing */
+       for (; ce2 != ce; ce2=ce2->ce_sibs) {
+               config_renumber_one( op, rs, ce2->ce_parent, ce2->ce_entry,
+                       count+old, 0, use_ldif );
+               count++;
+       }
+       return config_renumber_one( op, rs, ce->ce_parent, ce->ce_entry,
+               count+old, 0, use_ldif );
+}
+
 /* Parse an LDAP entry into config directives, then store in underlying
  * database.
  */
@@ -4122,17 +4305,27 @@ config_back_add( Operation *op, SlapReply *rs )
         * 1) check for existence of entry
         * 2) check for sibling renumbering
         * 3) perform internal add
-        * 4) store entry in underlying database
-        * 5) perform any necessary renumbering
+        * 4) perform any necessary renumbering
+        * 5) store entry in underlying database
         */
-       /* NOTE: by now we do not accept adds that require renumbering */
-       renumber = -1;
        rs->sr_err = config_add_internal( cfb, op->ora_e, &ca, rs, &renumber, op );
        if ( rs->sr_err != LDAP_SUCCESS ) {
                rs->sr_text = ca.msg;
                goto out2;
        }
 
+       if ( renumber ) {
+               CfEntryInfo *ce = ca.ca_entry->e_private;
+               req_add_s addr = op->oq_add;
+               op->o_tag = LDAP_REQ_MODRDN;
+               rs->sr_err = config_rename_add( op, rs, ce, ca.valx, 0, 0, cfb->cb_use_ldif );
+               op->o_tag = LDAP_REQ_ADD;
+               op->oq_add = addr;
+               if ( rs->sr_err != LDAP_SUCCESS ) {
+                       goto out2;
+               }
+       }
+
        if ( cfb->cb_use_ldif ) {
                BackendDB *be = op->o_bd;
                slap_callback sc = { NULL, slap_null_cb, NULL, NULL };
@@ -4155,10 +4348,6 @@ config_back_add( Operation *op, SlapReply *rs )
                op->o_ndn = ndn;
        }
 
-       if ( renumber ) {
-               /* TODO */
-       }
-
 out2:;
        ldap_pvt_thread_pool_resume( &connection_pool );
 
@@ -4521,6 +4710,8 @@ config_back_modrdn( Operation *op, SlapReply *rs )
 {
        CfBackInfo *cfb;
        CfEntryInfo *ce, *last;
+       struct berval rdn;
+       int ixold, ixnew;
 
        cfb = (CfBackInfo *)op->o_bd->be_private;
 
@@ -4555,10 +4746,153 @@ config_back_modrdn( Operation *op, SlapReply *rs )
                rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
                goto out;
        }
+
+       /* If newRDN == oldRDN, quietly succeed */
+       dnRdn( &op->o_req_ndn, &rdn );
+       if ( dn_match( &rdn, &op->orr_nnewrdn )) {
+               rs->sr_err = LDAP_SUCCESS;
+               goto out;
+       }
+
+       /* Current behavior, subject to change as needed:
+        *
+        * For backends and overlays, we only allow renumbering.
+        * For schema, we allow renaming with the same number.
+        * Otherwise, the op is not allowed.
+        */
+
+       if ( ce->ce_type == Cft_Schema ) {
+               char *ptr1, *ptr2;
+               int len;
+
+               /* Can't alter the main cn=schema entry */
+               if ( ce->ce_parent->ce_type == Cft_Global ) {
+                       rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
+                       rs->sr_text = "renaming not allowed for this entry";
+                       goto out;
+               }
+
+               /* We could support this later if desired */
+               ptr1 = ber_bvchr( &rdn, '}' );
+               ptr2 = ber_bvchr( &op->orr_newrdn, '}' );
+               len = ptr1 - rdn.bv_val;
+               if ( len != ptr2 - op->orr_newrdn.bv_val ||
+                       strncmp( rdn.bv_val, op->orr_newrdn.bv_val, len )) {
+                       rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
+                       rs->sr_text = "schema reordering not supported";
+                       goto out;
+               }
+       } else if ( ce->ce_type == Cft_Database ||
+               ce->ce_type == Cft_Overlay ) {
+               char *ptr1, *ptr2, *iptr1, *iptr2;
+               int len1, len2;
+
+               iptr2 = ber_bvchr( &op->orr_newrdn, '=' ) + 1;
+               if ( *iptr2 != '{' ) {
+                       rs->sr_err = LDAP_NAMING_VIOLATION;
+                       rs->sr_text = "new ordering index is required";
+                       goto out;
+               }
+               iptr2++;
+               iptr1 = ber_bvchr( &rdn, '{' ) + 1;
+               ptr1 = ber_bvchr( &rdn, '}' );
+               ptr2 = ber_bvchr( &op->orr_newrdn, '}' );
+               if ( !ptr2 ) {
+                       rs->sr_err = LDAP_NAMING_VIOLATION;
+                       rs->sr_text = "new ordering index is required";
+                       goto out;
+               }
+
+               len1 = ptr1 - rdn.bv_val;
+               len2 = ptr2 - op->orr_newrdn.bv_val;
+
+               if ( rdn.bv_len - len1 != op->orr_newrdn.bv_len - len2 ||
+                       strncmp( ptr1, ptr2, rdn.bv_len - len1 )) {
+                       rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
+                       rs->sr_text = "changing database/overlay type not allowed";
+                       goto out;
+               }
+               ixold = strtol( iptr1, NULL, 0 );
+               ixnew = strtol( iptr2, &ptr1, 0 );
+               if ( ptr1 != ptr2 || ixold < 0 || ixnew < 0 ) {
+                       rs->sr_err = LDAP_NAMING_VIOLATION;
+                       goto out;
+               }
+               /* config DB is always 0, cannot be changed */
+               if ( ce->ce_type == Cft_Database && ( ixold == 0 || ixnew == 0 )) {
+                       rs->sr_err = LDAP_CONSTRAINT_VIOLATION;
+                       goto out;
+               }
+       } else {
+               rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
+               rs->sr_text = "renaming not supported for this entry";
+               goto out;
+       }
+
        ldap_pvt_thread_pool_pause( &connection_pool );
 
-       rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
-       rs->sr_text = "renaming not implemented yet within naming context";
+       if ( ce->ce_type == Cft_Schema ) {
+               struct berval rdn;
+               Attribute *a;
+               rs->sr_err = config_rename_attr( rs, ce->ce_entry, &rdn, &a );
+               if ( rs->sr_err == LDAP_SUCCESS ) {
+                       rs->sr_err = config_rename_one( op, rs, ce->ce_entry,
+                               ce->ce_parent, a, &op->orr_newrdn, &op->orr_nnewrdn,
+                               cfb->cb_use_ldif );
+               }
+       } else {
+               CfEntryInfo *ce2, *cebase, **cprev, **cbprev, *ceold;
+               req_modrdn_s modr = op->oq_modrdn;
+               int i;
+
+               /* Advance to first of this type */
+               cprev = &ce->ce_parent->ce_kids;
+               for ( ce2 = *cprev; ce2 && ce2->ce_type != ce->ce_type; ) {
+                       cprev = &ce2->ce_sibs;
+                       ce2 = ce2->ce_sibs;
+               }
+               /* Skip the -1 entry */
+               if ( ce->ce_type == Cft_Database ) {
+                       cprev = &ce2->ce_sibs;
+                       ce2 = ce2->ce_sibs;
+               }
+               cebase = ce2;
+               cbprev = cprev;
+
+               /* Remove from old slot */
+               for ( ce2 = *cprev; ce2 && ce2 != ce; ce2 = ce2->ce_sibs )
+                       cprev = &ce2->ce_sibs;
+               *cprev = ce->ce_sibs;
+               ceold = ce->ce_sibs;
+
+               /* Insert into new slot */
+               cprev = cbprev;
+               for ( i=0; i<ixnew; i++ ) {
+                       ce2 = *cprev;
+                       if ( !ce2 )
+                               break;
+                       cprev = &ce2->ce_sibs;
+               }
+               ce->ce_sibs = *cprev;
+               *cprev = ce;
+
+               ixnew = i;
+
+               /* NOTE: These should be encoded in the OC tables, not inline here */
+               if ( ce->ce_type == Cft_Database )
+                       backend_db_move( ce->ce_be, ixnew );
+               else if ( ce->ce_type == Cft_Overlay )
+                       overlay_move( ce->ce_be, (slap_overinst *)ce->ce_bi, ixnew );
+                       
+               if ( ixold < ixnew ) {
+                       rs->sr_err = config_rename_del( op, rs, ce, ceold, ixold,
+                               cfb->cb_use_ldif );
+               } else {
+                       rs->sr_err = config_rename_add( op, rs, ce, ixnew, 1,
+                               ixold - ixnew, cfb->cb_use_ldif );
+               }
+               op->oq_modrdn = modr;
+       }
 
        ldap_pvt_thread_pool_resume( &connection_pool );
 out:
index 258519349e9e00f95ae07c5fa867b4eb86f1dce0..c2ac4c77acb6d61f64699931cc25778c834ca7fc 100644 (file)
@@ -417,6 +417,7 @@ slap_modrdn2mods(
                        goto done;
                }
        }
+       rs->sr_text = NULL;
 
        /* Add new attribute values to the entry */
        for ( a_cnt = 0; new_rdn[a_cnt]; a_cnt++ ) {
index ab93f7667fff24e0d1bfa62fa1ab974b7cd5b947..530a2bb341368c191d6eede20c43dbd8c9ad38dd 100644 (file)
@@ -1926,7 +1926,7 @@ pc_cf_gen( ConfigArgs *c )
                        return( 1 );
                }
 
-               if ( !backend_db_init( c->argv[1], &cm->db )) {
+               if ( !backend_db_init( c->argv[1], &cm->db, -1 )) {
                        snprintf( c->msg, sizeof( c->msg ), "unknown backend type (arg #1)" );
                        Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->msg, 0 );
                        return( 1 );
index c94d04b00a055238a7be084640094be6a53f9073..0ef846b2b3f1dc84f8bc3fd9eb25bfef2a90eb13 100644 (file)
@@ -699,7 +699,7 @@ static int translucent_db_init(BackendDB *be) {
        ov->db.be_private = NULL;
        ov->db.be_pcl_mutexp = &ov->db.be_pcl_mutex;
 
-       if ( !backend_db_init( "ldap", &ov->db )) {
+       if ( !backend_db_init( "ldap", &ov->db, -1 )) {
                Debug( LDAP_DEBUG_CONFIG, "translucent: unable to open captive back-ldap\n", 0, 0, 0);
                return 1;
        }
index 5f8b8743adcb1d0721ee27c46d5dffbfe0729b10..a0674ca2f36207f673d031e366f6574abd0f43d0 100644 (file)
@@ -323,7 +323,9 @@ LDAP_SLAPD_F (void) backend_destroy_one LDAP_P((BackendDB *bd, int dynamic));
 
 LDAP_SLAPD_F (BackendInfo *) backend_info LDAP_P(( const char *type ));
 LDAP_SLAPD_F (BackendDB *) backend_db_init LDAP_P(( const char *type,
-       BackendDB *be ));
+       BackendDB *be, int idx ));
+LDAP_SLAPD_F (void) backend_db_insert LDAP_P((BackendDB *bd, int idx));
+LDAP_SLAPD_F (void) backend_db_move LDAP_P((BackendDB *bd, int idx));
 
 LDAP_SLAPD_F (BackendDB *) select_backend LDAP_P((
        struct berval * dn,
@@ -411,7 +413,8 @@ LDAP_SLAPD_F (int) glue_sub_del( BackendDB *be );
  * backover.c
  */
 LDAP_SLAPD_F (int) overlay_register LDAP_P(( slap_overinst *on ));
-LDAP_SLAPD_F (int) overlay_config LDAP_P(( BackendDB *be, const char *ov ));
+LDAP_SLAPD_F (int) overlay_config LDAP_P(( BackendDB *be, const char *ov,
+       int idx, BackendInfo **res ));
 LDAP_SLAPD_F (void) overlay_destroy_one LDAP_P((
        BackendDB *be,
        slap_overinst *on ));
@@ -428,6 +431,10 @@ LDAP_SLAPD_F (int) overlay_op_walk LDAP_P((
        slap_operation_t which,
        slap_overinfo *oi,
        slap_overinst *on ));
+LDAP_SLAPD_F (void) overlay_insert LDAP_P((
+       BackendDB *be, slap_overinst *on, slap_overinst ***prev, int idx ));
+LDAP_SLAPD_F (void) overlay_move LDAP_P((
+       BackendDB *be, slap_overinst *on, int idx ));
 
 /*
  * bconfig.c
index cdd6e0f7c1c56378e69dddf9962e88311a48c19f..d359307bc08f7b8c7201f5ff1a6866e93c1cde26 100644 (file)
@@ -935,7 +935,7 @@ int slapi_over_config( BackendDB *be )
                slapi_over_initialized = 1;
        }
 
-       return overlay_config( be, SLAPI_OVERLAY_NAME );
+       return overlay_config( be, SLAPI_OVERLAY_NAME, -1, NULL );
 }
 
 #endif /* LDAP_SLAPI */