]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/back-bdb/modify.c
Plug memory leak
[openldap] / servers / slapd / back-bdb / modify.c
index 4f052e404ce7ad154f40c28389826ffcb1552116..3f267b03131ca2d99a1a3a48dc73f6b6245dd737 100644 (file)
@@ -166,9 +166,10 @@ int bdb_modify_internal(
                        e->e_ocflags = 0;
                }
 
-               /* check if modified attribute was indexed */
+               /* check if modified attribute was indexed
+                * but not in case of NOOP... */
                err = bdb_index_is_indexed( be, mod->sm_desc );
-               if ( err == LDAP_SUCCESS ) {
+               if ( err == LDAP_SUCCESS && !op->o_noop ) {
                        ap = attr_find( save_attrs, mod->sm_desc );
                        if ( ap ) ap->a_flags |= SLAP_ATTR_IXDEL;
 
@@ -179,17 +180,23 @@ int bdb_modify_internal(
 
        /* check that the entry still obeys the schema */
        rc = entry_schema_check( be, e, save_attrs, text, textbuf, textlen );
-       if ( rc != LDAP_SUCCESS ) {
+       if ( rc != LDAP_SUCCESS || op->o_noop ) {
                attrs_free( e->e_attrs );
                e->e_attrs = save_attrs;
+
+               if ( rc != LDAP_SUCCESS ) {
 #ifdef NEW_LOGGING
-                               LDAP_LOG ( OPERATION, ERR, 
-                                       "bdb_modify_internal: entry failed schema check %s\n", 
-                                       *text, 0, 0 );
+                       LDAP_LOG ( OPERATION, ERR, "bdb_modify_internal: "
+                               "entry failed schema check %s\n", 
+                               *text, 0, 0 );
 #else
-               Debug( LDAP_DEBUG_ANY, "entry failed schema check: %s\n",
-                       *text, 0, 0 );
+                       Debug( LDAP_DEBUG_ANY,
+                               "entry failed schema check: %s\n",
+                               *text, 0, 0 );
 #endif
+               }
+
+               /* if NOOP then silently revert to saved attrs */
                return rc;
        }
 
@@ -268,6 +275,14 @@ bdb_modify(
        u_int32_t       locker;
        DB_LOCK         lock;
 
+       int             noop = 0;
+
+#ifdef LDAP_CLIENT_UPDATE
+       Operation* ps_list;
+       struct psid_entry* pm_list;
+       struct psid_entry* pm_prev;
+#endif
+
 #ifdef NEW_LOGGING
        LDAP_LOG ( OPERATION, ENTRY, "bdb_modify: %s\n", dn->bv_val, 0, 0 );
 #else
@@ -286,6 +301,17 @@ retry:     /* transaction retry */
                Debug(LDAP_DEBUG_TRACE,
                        "bdb_modify: retrying...\n", 0, 0, 0);
 #endif
+
+#ifdef LDAP_CLIENT_UPDATE
+               pm_list = LDAP_LIST_FIRST(&op->premodify_list);
+               while ( pm_list != NULL ) {
+                       LDAP_LIST_REMOVE ( pm_list, link );
+                       pm_prev = pm_list;
+                       pm_list = LDAP_LIST_NEXT ( pm_list, link );
+                       free (pm_prev);
+               }
+#endif
+
                rc = TXN_ABORT( ltid );
                ltid = NULL;
                op->o_private = NULL;
@@ -396,6 +422,14 @@ retry:     /* transaction retry */
                ber_bvarray_free( refs );
                goto done;
        }
+
+#ifdef LDAP_CLIENT_UPDATE
+       if ( rc == LDAP_SUCCESS && !op->o_noop ) {
+               LDAP_LIST_FOREACH ( ps_list, &bdb->psearch_list, link ) {
+                       bdb_psearch(be, conn, op, ps_list, e, LCUP_PSEARCH_BY_PREMODIFY );
+               }
+       }
+#endif /* LDAP_CLIENT_UPDATE */
        
        /* Modify the entry */
        rc = bdb_modify_internal( be, conn, op, ltid, modlist, e,
@@ -439,7 +473,12 @@ retry:     /* transaction retry */
        }
 
        if( op->o_noop ) {
-               rc = TXN_ABORT( ltid );
+               if ( ( rc = TXN_ABORT( ltid ) ) != 0 ) {
+                       text = "txn_abort (no-op) failed";
+               } else {
+                       noop = 1;
+                       rc = LDAP_SUCCESS;
+               }
        } else {
                rc = TXN_COMMIT( ltid, 0 );
        }
@@ -479,6 +518,24 @@ return_results:
        send_ldap_result( conn, op, rc,
                NULL, text, NULL, NULL );
 
+#ifdef LDAP_CLIENT_UPDATE
+       if ( rc == LDAP_SUCCESS && !op->o_noop ) {
+               /* Loop through in-scope entries for each psearch spec */
+               LDAP_LIST_FOREACH ( ps_list, &bdb->psearch_list, link ) {
+                       bdb_psearch( be, conn, op, ps_list, e, LCUP_PSEARCH_BY_MODIFY );
+               }
+               pm_list = LDAP_LIST_FIRST(&op->premodify_list);
+               while ( pm_list != NULL ) {
+                       bdb_psearch(be, conn, op, pm_list->ps->op,
+                                               e, LCUP_PSEARCH_BY_SCOPEOUT);
+                       LDAP_LIST_REMOVE ( pm_list, link );
+                       pm_prev = pm_list;
+                       pm_list = LDAP_LIST_NEXT ( pm_list, link );
+                       free (pm_prev);
+               }
+       }
+#endif /* LDAP_CLIENT_UPDATE */
+
        if( rc == LDAP_SUCCESS && bdb->bi_txn_cp ) {
                ldap_pvt_thread_yield();
                TXN_CHECKPOINT( bdb->bi_dbenv,
@@ -487,6 +544,15 @@ return_results:
 
 done:
        if( ltid != NULL ) {
+#ifdef LDAP_CLIENT_UPDATE
+               pm_list = LDAP_LIST_FIRST(&op->premodify_list);
+               while ( pm_list != NULL ) {
+                       LDAP_LIST_REMOVE ( pm_list, link );
+                       pm_prev = pm_list;
+                       pm_list = LDAP_LIST_NEXT ( pm_list, link );
+                       free (pm_prev);
+               }
+#endif
                TXN_ABORT( ltid );
                op->o_private = NULL;
        }
@@ -494,5 +560,5 @@ done:
        if( e != NULL ) {
                bdb_unlocked_cache_return_entry_w (&bdb->bi_cache, e);
        }
-       return rc;
+       return ( ( rc == LDAP_SUCCESS ) ? noop : rc );
 }