Implement has_watches(Tx) transaction flag
Returns true if transaction has created any watches. If writes are disallowed,
watches are also cannot be created.
diff --git a/c_src/main.c b/c_src/main.c
index 4eb35a0..674b92b 100644
--- a/c_src/main.c
+++ b/c_src/main.c
@@ -818,6 +818,7 @@
t->txid = 0;
t->read_only = true;
t->writes_allowed = true;
+ t->has_watches = false;
ret = enif_make_resource(env, t);
enif_release_resource(t);
@@ -1659,6 +1660,13 @@
return enif_make_badarg(env);
}
+ // In order for the watches to fire the transaction must commit, even if it
+ // is a read-only transaction. So if writes are explicitly disallowed, also
+ // do not allow setting any watches.
+ if(!t->writes_allowed) {
+ return enif_raise_exception(env, ATOM_writes_not_allowed);
+ }
+
if(!enif_inspect_binary(env, argv[1], &key)) {
return enif_make_badarg(env);
}
@@ -1669,6 +1677,7 @@
key.size
);
+ t->has_watches = true;
return erlfdb_create_future(env, future, ErlFDB_FT_VOID);
}
@@ -1748,6 +1757,7 @@
t->txid = 0;
t->read_only = true;
+ t->has_watches = false;
return ATOM_ok;
}
@@ -1967,6 +1977,42 @@
static ERL_NIF_TERM
+erlfdb_transaction_has_watches(
+ ErlNifEnv* env,
+ int argc,
+ const ERL_NIF_TERM argv[]
+ )
+{
+ ErlFDBSt* st = (ErlFDBSt*) enif_priv_data(env);
+ ErlFDBTransaction* t;
+ void* res;
+
+ if(st->lib_state != ErlFDB_CONNECTED) {
+ return enif_make_badarg(env);
+ }
+
+ if(argc != 1) {
+ return enif_make_badarg(env);
+ }
+
+ if(!enif_get_resource(env, argv[0], ErlFDBTransactionRes, &res)) {
+ return enif_make_badarg(env);
+ }
+ t = (ErlFDBTransaction*) res;
+
+ if(!erlfdb_transaction_is_owner(env, t)) {
+ return enif_make_badarg(env);
+ }
+
+ if(t->has_watches) {
+ return ATOM_true;
+ } else {
+ return ATOM_false;
+ }
+}
+
+
+static ERL_NIF_TERM
erlfdb_transaction_get_writes_allowed(
ErlNifEnv* env,
int argc,
@@ -2111,6 +2157,7 @@
NIF_FUNC(erlfdb_transaction_get_approximate_size, 1),
NIF_FUNC(erlfdb_transaction_get_next_tx_id, 1),
NIF_FUNC(erlfdb_transaction_is_read_only, 1),
+ NIF_FUNC(erlfdb_transaction_has_watches, 1),
NIF_FUNC(erlfdb_transaction_get_writes_allowed, 1),
NIF_FUNC(erlfdb_get_error, 1),
diff --git a/c_src/resources.h b/c_src/resources.h
index bee88f6..6694a99 100644
--- a/c_src/resources.h
+++ b/c_src/resources.h
@@ -61,6 +61,7 @@
unsigned int txid;
bool read_only;
bool writes_allowed;
+ bool has_watches;
} ErlFDBTransaction;
diff --git a/src/erlfdb.erl b/src/erlfdb.erl
index 2f6460e..2b62b91 100644
--- a/src/erlfdb.erl
+++ b/src/erlfdb.erl
@@ -109,6 +109,7 @@
% Transaction status
get_next_tx_id/1,
is_read_only/1,
+ has_watches/1,
get_writes_allowed/1,
% Locality
@@ -594,6 +595,13 @@
is_read_only(?GET_TX(SS)).
+has_watches(?IS_TX = Tx) ->
+ erlfdb_nif:transaction_has_watches(Tx);
+
+has_watches(?IS_SS = SS) ->
+ has_watches(?GET_TX(SS)).
+
+
get_writes_allowed(?IS_TX = Tx) ->
erlfdb_nif:transaction_get_writes_allowed(Tx);
diff --git a/src/erlfdb_nif.erl b/src/erlfdb_nif.erl
index 755fe7c..2c0a944 100644
--- a/src/erlfdb_nif.erl
+++ b/src/erlfdb_nif.erl
@@ -52,6 +52,7 @@
transaction_add_conflict_range/4,
transaction_get_next_tx_id/1,
transaction_is_read_only/1,
+ transaction_has_watches/1,
transaction_get_writes_allowed/1,
transaction_get_approximate_size/1,
@@ -430,6 +431,11 @@
erlfdb_transaction_is_read_only(Tx).
+-spec transaction_has_watches(transaction()) -> true | false.
+transaction_has_watches({erlfdb_transaction, Tx}) ->
+ erlfdb_transaction_has_watches(Tx).
+
+
-spec transaction_get_writes_allowed(transaction()) -> true | false.
transaction_get_writes_allowed({erlfdb_transaction, Tx}) ->
erlfdb_transaction_get_writes_allowed(Tx).
@@ -575,6 +581,7 @@
) -> ?NOT_LOADED.
erlfdb_transaction_get_next_tx_id(_Transaction) -> ?NOT_LOADED.
erlfdb_transaction_is_read_only(_Transaction) -> ?NOT_LOADED.
+erlfdb_transaction_has_watches(_Transaction) -> ?NOT_LOADED.
erlfdb_transaction_get_writes_allowed(_Transaction) -> ?NOT_LOADED.
erlfdb_transaction_get_approximate_size(_Transaction) -> ?NOT_LOADED.
diff --git a/test/erlfdb_03_transaction_options_test.erl b/test/erlfdb_03_transaction_options_test.erl
index 7a68074..83c7fe7 100644
--- a/test/erlfdb_03_transaction_options_test.erl
+++ b/test/erlfdb_03_transaction_options_test.erl
@@ -59,5 +59,28 @@
end)).
+has_watches_test() ->
+ Db1 = erlfdb_util:get_test_db(),
+ {Before, After, AfterReset} = (erlfdb:transactional(Db1, fun(Tx) ->
+ Before = erlfdb:has_watches(Tx),
+ erlfdb:watch(Tx, gen(10)),
+ After = erlfdb:has_watches(Tx),
+ erlfdb:reset(Tx),
+ AfterReset = erlfdb:has_watches(Tx),
+ {Before, After, AfterReset}
+ end)),
+ ?assert(not Before),
+ ?assert(After),
+ ?assert(not AfterReset).
+
+
+cannot_set_watches_if_writes_disallowed_test() ->
+ Db1 = erlfdb_util:get_test_db(),
+ ?assertError(writes_not_allowed, erlfdb:transactional(Db1, fun(Tx) ->
+ erlfdb:set_option(Tx, disallow_writes),
+ erlfdb:watch(Tx, gen(10))
+ end)).
+
+
gen(Size) ->
crypto:strong_rand_bytes(Size).