Browse Source

tdb2: return TDB_ERR_RDONLY from transactions on R/O databases, log nesting

Rather than rturning TDB_ERR_EINVAL, return TDB_ERR_RDONLY, and log
when we fail due to nesting.
Rusty Russell 14 years ago
parent
commit
27647f9466
2 changed files with 25 additions and 8 deletions
  1. 22 6
      ccan/tdb2/tdb1_transaction.c
  2. 3 2
      ccan/tdb2/test/run-tdb1-nested-transactions.c

+ 22 - 6
ccan/tdb2/tdb1_transaction.c

@@ -418,18 +418,34 @@ static const struct tdb1_methods transaction1_methods = {
 static int _tdb1_transaction_start(struct tdb_context *tdb)
 {
 	/* some sanity checks */
-	if ((tdb->flags & TDB_RDONLY) || (tdb->flags & TDB_INTERNAL) || tdb->tdb1.traverse_read) {
-		tdb->last_error = tdb_logerr(tdb, TDB_ERR_EINVAL, TDB_LOG_USE_ERROR,
-					"tdb1_transaction_start: cannot start a"
-					" transaction on a read-only or"
-					" internal db");
+	if (tdb->flags & TDB_INTERNAL) {
+		tdb->last_error = tdb_logerr(tdb, TDB_ERR_EINVAL,
+					     TDB_LOG_USE_ERROR,
+					     "tdb1_transaction_start:"
+					     " cannot start a"
+					     " transaction on an"
+					     " internal tdb");
+		return -1;
+	}
+
+	if ((tdb->flags & TDB_RDONLY) || tdb->tdb1.traverse_read) {
+		tdb->last_error = tdb_logerr(tdb, TDB_ERR_RDONLY,
+					     TDB_LOG_USE_ERROR,
+					     "tdb_transaction_start:"
+					     " cannot start a"
+					     " transaction on a "
+					     " read-only tdb");
 		return -1;
 	}
 
 	/* cope with nested tdb1_transaction_start() calls */
 	if (tdb->tdb1.transaction != NULL) {
 		if (!(tdb->flags & TDB_ALLOW_NESTING)) {
-			tdb->last_error = TDB_ERR_EINVAL;
+			tdb->last_error
+				= tdb_logerr(tdb, TDB_ERR_EINVAL,
+					     TDB_LOG_USE_ERROR,
+					     "tdb_transaction_start:"
+					     " already inside transaction");
 			return -1;
 		}
 		tdb->stats.transaction_nest++;

+ 3 - 2
ccan/tdb2/test/run-tdb1-nested-transactions.c

@@ -15,7 +15,7 @@ int main(int argc, char *argv[])
 	hsize.base.next = &tap_log_attr;
 	hsize.tdb1_hashsize.hsize = 1024;
 
-	plan_tests(29);
+	plan_tests(30);
 	key.dsize = strlen("hi");
 	key.dptr = (void *)"hi";
 
@@ -33,6 +33,7 @@ int main(int argc, char *argv[])
 	ok1(memcmp(data.dptr, "world", strlen("world")) == 0);
 	free(data.dptr);
 	ok1(tdb_transaction_start(tdb) == TDB_ERR_EINVAL);
+	ok1(tap_log_messages == 1);
 
 	ok1(tdb_fetch(tdb, key, &data) == TDB_SUCCESS);
 	ok1(data.dsize == strlen("world"));
@@ -55,7 +56,7 @@ int main(int argc, char *argv[])
 	ok1(tdb_transaction_commit(tdb) == TDB_SUCCESS);
 	ok1(!tdb_exists(tdb, key));
 	tdb_transaction_cancel(tdb);
-	ok1(tap_log_messages == 0);
+	ok1(tap_log_messages == 1);
 	/* Surprise! Kills inner "committed" transaction. */
 	ok1(tdb_exists(tdb, key));