]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/back-bdb/modrdn.c
Fix prev cache.c commit
[openldap] / servers / slapd / back-bdb / modrdn.c
index 16025c4c486eb446d76bc4647401ca1af97f3e7c..117cb05c25b2d0b939799a98b2c21e8930f1104c 100644 (file)
@@ -2,7 +2,7 @@
 /* $OpenLDAP$ */
 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
  *
- * Copyright 2000-2005 The OpenLDAP Foundation.
+ * Copyright 2000-2008 The OpenLDAP Foundation.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -33,8 +33,6 @@ bdb_modrdn( Operation *op, SlapReply *rs )
        Entry           *p = NULL;
        EntryInfo       *ei = NULL, *eip = NULL, *nei = NULL, *neip = NULL;
        /* LDAP v2 supporting correct attribute handling. */
-       LDAPRDN         new_rdn = NULL;
-       LDAPRDN         old_rdn = NULL;
        char textbuf[SLAP_TEXT_BUFLEN];
        size_t textlen = sizeof textbuf;
        DB_TXN          *ltid = NULL, *lt2;
@@ -46,12 +44,9 @@ bdb_modrdn( Operation        *op, SlapReply *rs )
        struct berval   *np_ndn = NULL;                 /* newSuperior ndn */
        struct berval   *new_parent_dn = NULL;  /* np_dn, p_dn, or NULL */
 
-       /* Used to interface with bdb_modify_internal() */
-       Modifications   *mod = NULL;            /* Used to delete old rdn */
-
        int             manageDSAit = get_manageDSAit( op );
 
-       u_int32_t       locker = 0;
+       BDB_LOCKER      locker = 0;
        DB_LOCK         lock, plock, nplock;
 
        int             num_retries = 0;
@@ -66,12 +61,56 @@ bdb_modrdn( Operation       *op, SlapReply *rs )
        int parent_is_glue = 0;
        int parent_is_leaf = 0;
 
-       ctrls[num_ctrls] = NULL;
+#ifdef LDAP_X_TXN
+       int settle = 0;
+#endif
 
        Debug( LDAP_DEBUG_TRACE, "==>" LDAP_XSTRING(bdb_modrdn) "(%s,%s,%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" );
 
+#ifdef LDAP_X_TXN
+       if( op->o_txnSpec ) {
+               /* acquire connection lock */
+               ldap_pvt_thread_mutex_lock( &op->o_conn->c_mutex );
+               if( op->o_conn->c_txn == CONN_TXN_INACTIVE ) {
+                       rs->sr_text = "invalid transaction identifier";
+                       rs->sr_err = LDAP_X_TXN_ID_INVALID;
+                       goto txnReturn;
+               } else if( op->o_conn->c_txn == CONN_TXN_SETTLE ) {
+                       settle=1;
+                       goto txnReturn;
+               }
+
+               if( op->o_conn->c_txn_backend == NULL ) {
+                       op->o_conn->c_txn_backend = op->o_bd;
+
+               } else if( op->o_conn->c_txn_backend != op->o_bd ) {
+                       rs->sr_text = "transaction cannot span multiple database contexts";
+                       rs->sr_err = LDAP_AFFECTS_MULTIPLE_DSAS;
+                       goto txnReturn;
+               }
+
+               /* insert operation into transaction */
+
+               rs->sr_text = "transaction specified";
+               rs->sr_err = LDAP_X_TXN_SPECIFY_OKAY;
+
+txnReturn:
+               /* release connection lock */
+               ldap_pvt_thread_mutex_unlock( &op->o_conn->c_mutex );
+
+               if( !settle ) {
+                       send_ldap_result( op, rs );
+                       return rs->sr_err;
+               }
+       }
+#endif
+
+       ctrls[num_ctrls] = NULL;
+
+       slap_mods_opattrs( op, &op->orr_modlist, 1 );
+
        if( 0 ) {
 retry: /* transaction retry */
                if ( dummy.e_attrs ) {
@@ -108,7 +147,6 @@ retry:      /* transaction retry */
                }
                parent_is_glue = 0;
                parent_is_leaf = 0;
-               ldap_pvt_thread_yield();
                bdb_trans_backoff( ++num_retries );
        }
 
@@ -129,7 +167,6 @@ retry:      /* transaction retry */
 
        opinfo.boi_bdb = op->o_bd;
        opinfo.boi_txn = ltid;
-       opinfo.boi_locker = locker;
        opinfo.boi_err = 0;
        opinfo.boi_acl_cache = op->o_do_not_cache;
        op->o_private = &opinfo;
@@ -265,11 +302,11 @@ retry:    /* transaction retry */
                dnParent( &e->e_nname, &p_ndn );
        }
        np_ndn = &p_ndn;
-       if ( p_ndn.bv_len != 0 ) {
+       eip = ei->bei_parent;
+       if ( eip && eip->bei_id ) {
                /* Make sure parent entry exist and we can write its 
                 * children.
                 */
-               eip = ei->bei_parent;
                rs->sr_err = bdb_cache_find_id( op, ltid,
                        eip->bei_id, &eip, 0, locker, &plock );
 
@@ -373,8 +410,8 @@ retry:      /* transaction retry */
                        /* newSuperior == oldParent? - checked above */
                        /* newSuperior == entry being moved?, if so ==> ERROR */
                        if ( dnIsSuffix( np_ndn, &e->e_nname )) {
-                               rs->sr_err = LDAP_NAMING_VIOLATION;
-                               rs->sr_text = "new superior is invalid";
+                               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? */
@@ -404,7 +441,7 @@ retry:      /* transaction retry */
                                        ": newSup(ndn=%s) not here!\n",
                                        np_ndn->bv_val, 0, 0);
                                rs->sr_text = "new superior not found";
-                               rs->sr_err = LDAP_OTHER;
+                               rs->sr_err = LDAP_NO_SUCH_OBJECT;
                                goto return_results;
                        }
 
@@ -504,6 +541,8 @@ retry:      /* transaction retry */
                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, LDAP_XSTRING(bdb_modrdn) ": new ndn=%s\n",
@@ -511,7 +550,7 @@ retry:      /* transaction retry */
 
        /* Shortcut the search */
        nei = neip ? neip : eip;
-       rs->sr_err = bdb_cache_find_ndn ( op, ltid, &new_ndn, &nei );
+       rs->sr_err = bdb_cache_find_ndn ( op, locker, &new_ndn, &nei );
        if ( nei ) bdb_cache_entryinfo_unlock( nei );
        switch( rs->sr_err ) {
        case DB_LOCK_DEADLOCK:
@@ -520,6 +559,9 @@ retry:      /* transaction retry */
        case DB_NOTFOUND:
                break;
        case 0:
+               /* Allow rename to same DN */
+               if ( nei == ei )
+                       break;
                rs->sr_err = LDAP_ALREADY_EXISTS;
                goto return_results;
        default:
@@ -528,48 +570,7 @@ retry:     /* transaction retry */
                goto return_results;
        }
 
-       /* Get attribute type and attribute value of our new rdn, we will
-        * need to add that to our new entry
-        */
-       if ( !new_rdn && ldap_bv2rdn_x( &op->oq_modrdn.rs_newrdn, &new_rdn,
-               (char **)&rs->sr_text, LDAP_DN_FORMAT_LDAP, op->o_tmpmemctx ) )
-       {
-               Debug( LDAP_DEBUG_TRACE,
-                       LDAP_XSTRING(bdb_modrdn) ": can't figure out "
-                       "type(s)/values(s) of newrdn\n", 
-                       0, 0, 0 );
-               rs->sr_err = LDAP_INVALID_DN_SYNTAX;
-               rs->sr_text = "unknown type(s) used in RDN";
-               goto return_results;
-       }
-
-       Debug( LDAP_DEBUG_TRACE,
-               LDAP_XSTRING(bdb_modrdn)
-               ": new_rdn_type=\"%s\", new_rdn_val=\"%s\"\n",
-               new_rdn[ 0 ]->la_attr.bv_val,
-               new_rdn[ 0 ]->la_value.bv_val, 0 );
-
-       if ( op->oq_modrdn.rs_deleteoldrdn ) {
-               if ( !old_rdn && ldap_bv2rdn_x( &op->o_req_dn, &old_rdn,
-                       (char **)&rs->sr_text, LDAP_DN_FORMAT_LDAP, op->o_tmpmemctx ) )
-               {
-                       Debug( LDAP_DEBUG_TRACE,
-                               LDAP_XSTRING(bdb_modrdn) ": can't figure out "
-                               "the old_rdn type(s)/value(s)\n", 
-                               0, 0, 0 );
-                       rs->sr_err = LDAP_OTHER;
-                       rs->sr_text = "cannot parse RDN from old DN";
-                       goto return_results;            
-               }
-       }
-
-       /* prepare modlist of modifications from old/new rdn */
-       if (!mod) {
-               rs->sr_err = slap_modrdn2mods( op, rs, e, old_rdn, new_rdn, &mod );
-               if ( rs->sr_err != LDAP_SUCCESS ) {
-                       goto return_results;
-               }
-       }
+       assert( op->orr_modlist != NULL );
 
        if( op->o_preread ) {
                if( preread_ctrl == NULL ) {
@@ -581,8 +582,12 @@ retry:     /* transaction retry */
                {
                        Debug( LDAP_DEBUG_TRACE,        
                                "<=- " LDAP_XSTRING(bdb_modrdn)
-                               ": post-read failed!\n", 0, 0, 0 );
-                       goto return_results;
+                               ": pre-read failed!\n", 0, 0, 0 );
+                       if ( op->o_preread & SLAP_CONTROL_CRITICAL ) {
+                               /* FIXME: is it correct to abort
+                                * operation if control fails? */
+                               goto return_results;
+                       }
                }                   
        }
 
@@ -642,7 +647,7 @@ retry:      /* transaction retry */
        dummy.e_attrs = e->e_attrs;
 
        /* modify entry */
-       rs->sr_err = bdb_modify_internal( op, lt2, &mod[0], &dummy,
+       rs->sr_err = bdb_modify_internal( op, lt2, op->orr_modlist, &dummy,
                &rs->sr_text, textbuf, textlen );
        if( rs->sr_err != LDAP_SUCCESS ) {
                Debug(LDAP_DEBUG_TRACE,
@@ -720,7 +725,11 @@ retry:     /* transaction retry */
                        Debug( LDAP_DEBUG_TRACE,        
                                "<=- " LDAP_XSTRING(bdb_modrdn)
                                ": post-read failed!\n", 0, 0, 0 );
-                       goto return_results;
+                       if ( op->o_postread & SLAP_CONTROL_CRITICAL ) {
+                               /* FIXME: is it correct to abort
+                                * operation if control fails? */
+                               goto return_results;
+                       }
                }                   
        }
 
@@ -728,7 +737,10 @@ retry:     /* transaction retry */
                if(( rs->sr_err=TXN_ABORT( ltid )) != 0 ) {
                        rs->sr_text = "txn_abort (no-op) failed";
                } else {
-                       rs->sr_err = LDAP_SUCCESS;
+                       rs->sr_err = LDAP_X_NO_OPERATION;
+                       ltid = NULL;
+                       /* Only free attrs if they were dup'd.  */
+                       if ( dummy.e_attrs == e->e_attrs ) dummy.e_attrs = NULL;
                        goto return_results;
                }
 
@@ -777,8 +789,7 @@ return_results:
        }
        send_ldap_result( op, rs );
 
-       if( rs->sr_err == LDAP_SUCCESS && bdb->bi_txn_cp ) {
-               ldap_pvt_thread_yield();
+       if( rs->sr_err == LDAP_SUCCESS && bdb->bi_txn_cp_kbyte ) {
                TXN_CHECKPOINT( bdb->bi_dbenv,
                        bdb->bi_txn_cp_kbyte, bdb->bi_txn_cp_min, 0 );
        }
@@ -788,31 +799,11 @@ return_results:
        }
 
 done:
+       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 );
 
-       /* LDAP v2 supporting correct attribute handling. */
-       if ( new_rdn != NULL ) {
-               ldap_rdnfree_x( new_rdn, op->o_tmpmemctx );
-       }
-       if ( old_rdn != NULL ) {
-               ldap_rdnfree_x( old_rdn, op->o_tmpmemctx );
-       }
-       if( mod != NULL ) {
-               Modifications *tmp;
-               for (; mod; mod=tmp ) {
-                       tmp = mod->sml_next;
-                       /* slap_modrdn2mods does things one way,
-                        * slap_mods_opattrs does it differently
-                        */
-                       if ( mod->sml_op != SLAP_MOD_SOFTADD &&
-                               mod->sml_op != LDAP_MOD_DELETE ) break;
-                       if ( mod->sml_nvalues ) free( mod->sml_nvalues[0].bv_val );
-                       free( mod );
-               }
-               slap_mods_free( mod, 1 );
-       }
-
        /* LDAP v3 Support */
        if( np != NULL ) {
                /* free new parent and reader lock */
@@ -831,14 +822,14 @@ done:
 
        if( ltid != NULL ) {
                TXN_ABORT( ltid );
-               op->o_private = NULL;
        }
+       op->o_private = NULL;
 
-       if( preread_ctrl != NULL ) {
+       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 ) {
+       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 );
        }