ldb-tools: Place the whole of an ldif file in a transaction
authorAndrew Bartlett <abartlet@samba.org>
Wed, 4 Apr 2012 05:17:32 +0000 (15:17 +1000)
committerAndrew Bartlett <abartlet@samba.org>
Tue, 10 Apr 2012 09:14:43 +0000 (11:14 +0200)
This ensures that when operating ldbadd and ldbmodify against local
ldb files, either an ldif file succeeds or fails as a whole.

Also tests to verify that this is working correctly, and an ABI bump
due to the extra (private, but exported to ldb* tools) symbol and
behaviour change.

Andrew Bartlett

Autobuild-User: Andrew Bartlett <abartlet@samba.org>
Autobuild-Date: Tue Apr 10 11:14:43 CEST 2012 on sn-devel-104

lib/ldb/tests/test-dup-2.ldif [new file with mode: 0644]
lib/ldb/tests/test-dup.ldif [new file with mode: 0644]
lib/ldb/tests/test-generic.sh
lib/ldb/tests/test-modify-unmet-2.ldif [new file with mode: 0644]
lib/ldb/tests/test-modify-unmet.ldif [new file with mode: 0644]
lib/ldb/tools/ldbadd.c
lib/ldb/tools/ldbmodify.c

diff --git a/lib/ldb/tests/test-dup-2.ldif b/lib/ldb/tests/test-dup-2.ldif
new file mode 100644 (file)
index 0000000..a426101
--- /dev/null
@@ -0,0 +1,6 @@
+dn: cn=Sentinel,ou=Alumni Association,ou=People,o=University of Michigan,c=TEST
+objectclass: OpenLDAPperson
+cn: Sentinel
+sn: USER
+uid: USER, Sentinel
+
diff --git a/lib/ldb/tests/test-dup.ldif b/lib/ldb/tests/test-dup.ldif
new file mode 100644 (file)
index 0000000..b35420b
--- /dev/null
@@ -0,0 +1,13 @@
+dn: cn=Fred Bassett,ou=Alumni Association,ou=People,o=University of Michigan,c=TEST
+objectclass: OpenLDAPperson
+cn: Fred Bassett
+sn: Bassett
+uid: Bassett, Fred
+
+dn: cn=Sentinel,ou=Alumni Association,ou=People,o=University of Michigan,c=TEST
+objectclass: OpenLDAPperson
+cn: Sentinel
+sn: USER
+uid: USER, Sentinel
+
+
index 9c45ed9614a0a023343c11fbb0ad480b039e72d9..69f901bd7cd79583e94946ee4a20bd2f051dd354 100755 (executable)
@@ -16,9 +16,30 @@ $VALGRIND ldbadd $LDBDIR/tests/test.ldif 2> /dev/null && {
     exit 1
 }
 
+echo "Adding LDIF with one already-existing user again - should fail"
+$VALGRIND ldbadd $LDBDIR/tests/test-dup.ldif 2> /dev/null && {
+    echo "Should have failed to add again - gave $?"
+    exit 1
+}
+
+echo "Adding again - should succeed (as previous failed)"
+$VALGRIND ldbadd $LDBDIR/tests/test-dup-2.ldif || exit 1
+
 echo "Modifying elements"
 $VALGRIND ldbmodify $LDBDIR/tests/test-modify.ldif || exit 1
 
+echo "Modify LDIF with one un-met constraint - should fail"
+$VALGRIND ldbadd $LDBDIR/tests/test-modify-unmet.ldif 2> /dev/null && {
+    echo "Should have failed to modify - gave $?"
+    exit 1
+}
+
+echo "Modify LDIF with after failure of un-met constraint - should also fail"
+$VALGRIND ldbadd $LDBDIR/tests/test-modify-unmet-2.ldif 2> /dev/null && {
+    echo "Should have failed to modify - gave $?"
+    exit 1
+}
+
 echo "Showing modified record"
 $VALGRIND ldbsearch '(uid=uham)'  || exit 1
 
diff --git a/lib/ldb/tests/test-modify-unmet-2.ldif b/lib/ldb/tests/test-modify-unmet-2.ldif
new file mode 100644 (file)
index 0000000..8760938
--- /dev/null
@@ -0,0 +1,7 @@
+dn: cn=Sentinel,ou=Alumni Association,ou=People,o=University of Michiga
+ n,c=TEST
+changetype: modify
+delete: drink
+drink: water
+
diff --git a/lib/ldb/tests/test-modify-unmet.ldif b/lib/ldb/tests/test-modify-unmet.ldif
new file mode 100644 (file)
index 0000000..6a46cdf
--- /dev/null
@@ -0,0 +1,15 @@
+dn: cn=Sentinel,ou=Alumni Association,ou=People,o=University of Michiga
+ n,c=TEST
+changetype: modify
+add: drink
+drink: water
+
+dn: cn=Sentinel,ou=Alumni Association,ou=People,o=University of Michiga
+ n,c=TEST
+changetype: modify
+add: sn
+sn: TEST
+-
+delete: sn
+sn: USER2
+
index 47fd261841642cff3841b51d75349593ddff4144..d0d5ec0ec4078114063fb4ac35c95a906c988015 100644 (file)
@@ -34,8 +34,8 @@
 #include "ldb.h"
 #include "tools/cmdline.h"
 #include "ldbutil.h"
+#include "include/ldb_private.h"
 
-static unsigned int failures;
 static struct ldb_cmdline *options;
 
 static void usage(struct ldb_context *ldb)
@@ -55,13 +55,23 @@ static int process_file(struct ldb_context *ldb, FILE *f, unsigned int *count)
        struct ldb_ldif *ldif;
        int fun_ret = LDB_SUCCESS, ret;
         struct ldb_control **req_ctrls = ldb_parse_control_strings(ldb, ldb, (const char **)options->controls);
+       struct ldif_read_file_state state = {
+               .f = f
+       };
+
        if (options->controls != NULL &&  req_ctrls== NULL) {
                printf("parsing controls failed: %s\n", ldb_errstring(ldb));
                return LDB_ERR_OPERATIONS_ERROR;
        }
 
+       fun_ret = ldb_transaction_start(ldb);
+       if (fun_ret != LDB_SUCCESS) {
+               fprintf(stderr, "ERR: (%s) on transaction start\n",
+                       ldb_errstring(ldb));
+               return fun_ret;
+       }
 
-       while ((ldif = ldb_ldif_read_file(ldb, f))) {
+       while ((ldif = ldb_ldif_read_file_state(ldb, &state))) {
                if (ldif->changetype != LDB_CHANGETYPE_ADD &&
                    ldif->changetype != LDB_CHANGETYPE_NONE) {
                        fprintf(stderr, "Only CHANGETYPE_ADD records allowed\n");
@@ -73,7 +83,6 @@ static int process_file(struct ldb_context *ldb, FILE *f, unsigned int *count)
                        fprintf(stderr,
                                "ERR: Message canonicalize failed - %s\n",
                                ldb_strerror(ret));
-                       failures++;
                        fun_ret = ret;
                        ldb_ldif_read_free(ldb, ldif);
                        continue;
@@ -81,10 +90,10 @@ static int process_file(struct ldb_context *ldb, FILE *f, unsigned int *count)
 
                ret = ldb_add_ctrl(ldb, ldif->msg,req_ctrls);
                if (ret != LDB_SUCCESS) {
-                       fprintf(stderr, "ERR: %s : \"%s\" on DN %s\n",
+                       fprintf(stderr, "ERR: %s : \"%s\" on DN %s at block before line %llu\n",
                                ldb_strerror(ret), ldb_errstring(ldb),
-                               ldb_dn_get_linearized(ldif->msg->dn));
-                       failures++;
+                               ldb_dn_get_linearized(ldif->msg->dn),
+                               (unsigned long long)state.line_no);
                        fun_ret = ret;
                } else {
                        (*count)++;
@@ -93,6 +102,24 @@ static int process_file(struct ldb_context *ldb, FILE *f, unsigned int *count)
                        }
                }
                ldb_ldif_read_free(ldb, ldif);
+               if (ret) {
+                       break;
+               }
+       }
+
+       if (fun_ret == LDB_SUCCESS && !feof(f)) {
+               fprintf(stderr, "Failed to parse ldif\n");
+               fun_ret = LDB_ERR_OPERATIONS_ERROR;
+       }
+
+       if (fun_ret == LDB_SUCCESS) {
+               fun_ret = ldb_transaction_commit(ldb);
+               if (fun_ret != LDB_SUCCESS) {
+                       fprintf(stderr, "ERR: (%s) on transaction commit\n",
+                               ldb_errstring(ldb));
+               }
+       } else {
+               ldb_transaction_cancel(ldb);
        }
 
        return fun_ret;
@@ -148,7 +175,11 @@ int main(int argc, const char **argv)
 
        talloc_free(mem_ctx);
 
-       printf("Added %u records with %u failures\n", count, failures);
+       if (ret) {
+               printf("Add failed after processing %u records\n", count);
+       } else {
+               printf("Added %u records successfully\n", count);
+       }
 
        return ret;
 }
index 2ca7b62b2c367c563576c2772a679b32fd5978b7..3a9a2657ceeae1dbf989636862038648e8d44781 100644 (file)
@@ -34,8 +34,8 @@
 #include "ldb.h"
 #include "tools/cmdline.h"
 #include "ldbutil.h"
+#include "include/ldb_private.h"
 
-static unsigned int failures;
 static struct ldb_cmdline *options;
 
 static void usage(struct ldb_context *ldb)
@@ -54,13 +54,23 @@ static int process_file(struct ldb_context *ldb, FILE *f, unsigned int *count)
        struct ldb_ldif *ldif;
        int fun_ret = LDB_SUCCESS, ret;
        struct ldb_control **req_ctrls = ldb_parse_control_strings(ldb, ldb, (const char **)options->controls);
+       struct ldif_read_file_state state = {
+               .f = f
+       };
 
        if (options->controls != NULL &&  req_ctrls== NULL) {
                printf("parsing controls failed: %s\n", ldb_errstring(ldb));
                exit(LDB_ERR_OPERATIONS_ERROR);
        }
 
-       while ((ldif = ldb_ldif_read_file(ldb, f))) {
+       fun_ret = ldb_transaction_start(ldb);
+       if (fun_ret != LDB_SUCCESS) {
+               fprintf(stderr, "ERR: (%s) on transaction start\n",
+                       ldb_errstring(ldb));
+               return fun_ret;
+       }
+
+       while ((ldif = ldb_ldif_read_file_state(ldb, &state))) {
                struct ldb_dn *olddn;
                bool deleteoldrdn = false;
                struct ldb_dn *newdn;
@@ -96,10 +106,10 @@ static int process_file(struct ldb_context *ldb, FILE *f, unsigned int *count)
                        if (errstr == NULL) {
                                errstr = ldb_errstring(ldb);
                        }
-                       fprintf(stderr, "ERR: (%s) \"%s\" on DN %s\n",
+                       fprintf(stderr, "ERR: (%s) \"%s\" on DN %s at block before line %llu\n",
                                ldb_strerror(ret),
-                               errstr, ldb_dn_get_linearized(ldif->msg->dn));
-                       failures++;
+                               errstr, ldb_dn_get_linearized(ldif->msg->dn)
+                               (unsigned long long)state.line_no);
                        fun_ret = ret;
                } else {
                        (*count)++;
@@ -108,13 +118,26 @@ static int process_file(struct ldb_context *ldb, FILE *f, unsigned int *count)
                        }
                }
                ldb_ldif_read_free(ldb, ldif);
+               if (ret) {
+                       break;
+               }
        }
-
-       if (!feof(f)) {
+       
+       if (fun_ret == LDB_SUCCESS && !feof(f)) {
                fprintf(stderr, "Failed to parse ldif\n");
                fun_ret = LDB_ERR_OPERATIONS_ERROR;
        }
 
+       if (fun_ret == LDB_SUCCESS) {
+               fun_ret = ldb_transaction_commit(ldb);
+               if (fun_ret != LDB_SUCCESS) {
+                       fprintf(stderr, "ERR: (%s) on transaction commit\n",
+                               ldb_errstring(ldb));
+               }
+       } else {
+               ldb_transaction_cancel(ldb);
+       }
+
        return fun_ret;
 }
 
@@ -150,7 +173,11 @@ int main(int argc, const char **argv)
 
        talloc_free(mem_ctx);
 
-       printf("Modified %u records with %u failures\n", count, failures);
-
+       if (ret) {
+               printf("Modify failed after processing %u records\n", count);
+       } else {
+               printf("Modified %u records successfully\n", count);
+       }
+               
        return ret;
 }