tdb_compat: make tdb2s temporarily read-only for tdb_traverse_read()
authorRusty Russell <rusty@rustcorp.com.au>
Tue, 13 Sep 2011 21:47:13 +0000 (07:17 +0930)
committerRusty Russell <rusty@rustcorp.com.au>
Tue, 13 Sep 2011 21:47:13 +0000 (07:17 +0930)
It doesn't make a difference unless the tdb2 opens a TDB1 on disk, in
which case tdb1_traverse() takes a write lock on the entire file.  By
setting the tdb to read-only first, we simulate the old behaviour.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
lib/tdb_compat/tdb_compat.c
lib/tdb_compat/tdb_compat.h

index d736db1742e2d99b60ea3bfeaa47df00b03c9847..2e43564802242b62c872b9b643234eed3c93f2f6 100644 (file)
@@ -38,6 +38,26 @@ enum TDB_ERROR tdb_transaction_start_nonblock(struct tdb_context *tdb)
        return ecode;
 }
 
+/* For TDB1 tdbs, read traverse vs normal matters: write traverse
+   locks the entire thing! */
+int64_t tdb_traverse_read_(struct tdb_context *tdb,
+                          int (*fn)(struct tdb_context *,
+                                                      TDB_DATA, TDB_DATA,
+                                                      void *),
+                          void *p)
+{
+       int64_t ret;
+
+       if (tdb_get_flags(tdb) & TDB_RDONLY) {
+               return tdb_traverse(tdb, fn, p);
+       }
+
+       tdb_add_flag(tdb, TDB_RDONLY);
+       ret = tdb_traverse(tdb, fn, p);
+       tdb_remove_flag(tdb, TDB_RDONLY);
+       return ret;
+}
+
 /*
  * This handles TDB_CLEAR_IF_FIRST.
  */
index 80fc3cef8033817afb6990095ad6afa64b4fa296..16d1f48c7d613108db092ccc167290c47e7e7926 100644 (file)
@@ -62,8 +62,13 @@ static inline TDB_DATA tdb_nextkey_compat(struct tdb_context *tdb, TDB_DATA k)
        return k;
 }
 
-/* tdb_traverse_read and tdb_traverse are equal: both only take read locks. */
-#define tdb_traverse_read tdb_traverse
+#define tdb_traverse_read(tdb, fn, p)                                  \
+       tdb_traverse_read_(tdb, typesafe_cb_preargs(int, void *, (fn), (p), \
+                                                   struct tdb_context *, \
+                                                   TDB_DATA, TDB_DATA), (p))
+int64_t tdb_traverse_read_(struct tdb_context *tdb,
+                          int (*fn)(struct tdb_context *,
+                                    TDB_DATA, TDB_DATA, void *), void *p);
 
 /* Old-style tdb_errorstr */
 #define tdb_errorstr_compat(tdb) tdb_errorstr(tdb_error(tdb))