Add get_next_tx_id API
This API provides a transaction ID that can be used in the 12 byte
version stamps to distinguish between version stamps created in a single
transaction. There's a limit of 65,535 transaction ids afterwhich this
function starts throwing badarg exceptions.
diff --git a/c_src/main.c b/c_src/main.c
index 8321261..c6aeb6a 100644
--- a/c_src/main.c
+++ b/c_src/main.c
@@ -863,6 +863,7 @@
enif_self(env, &pid);
t->owner = enif_make_pid(env, &pid);
+ t->txid = 0;
t->read_only = true;
ret = enif_make_resource(env, t);
@@ -1761,6 +1762,8 @@
}
fdb_transaction_reset(t->transaction);
+
+ t->txid = 0;
t->read_only = true;
return ATOM_ok;
@@ -1871,6 +1874,42 @@
static ERL_NIF_TERM
+erlfdb_transaction_get_next_tx_id(
+ 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->txid > 65535) {
+ return enif_make_badarg(env);
+ }
+
+ return enif_make_uint(env, t->txid++);
+}
+
+
+static ERL_NIF_TERM
erlfdb_transaction_is_read_only(
ErlNifEnv* env,
int argc,
@@ -2015,6 +2054,7 @@
NIF_FUNC(erlfdb_transaction_reset, 1),
NIF_FUNC(erlfdb_transaction_cancel, 1),
NIF_FUNC(erlfdb_transaction_add_conflict_range, 4),
+ NIF_FUNC(erlfdb_transaction_get_next_tx_id, 1),
NIF_FUNC(erlfdb_transaction_is_read_only, 1),
NIF_FUNC(erlfdb_get_error, 1),
diff --git a/c_src/resources.h b/c_src/resources.h
index 5e230a0..798b22f 100644
--- a/c_src/resources.h
+++ b/c_src/resources.h
@@ -66,6 +66,7 @@
{
FDBTransaction* transaction;
ERL_NIF_TERM owner;
+ unsigned int txid;
bool read_only;
} ErlFDBTransaction;
diff --git a/src/erlfdb.erl b/src/erlfdb.erl
index 92102ba..d248c88 100644
--- a/src/erlfdb.erl
+++ b/src/erlfdb.erl
@@ -102,6 +102,7 @@
get_versionstamp/1,
% Transaction status
+ get_next_tx_id/1,
is_read_only/1,
% Locality
@@ -580,6 +581,13 @@
get_versionstamp(?GET_TX(SS)).
+get_next_tx_id(?IS_TX = Tx) ->
+ erlfdb_nif:transaction_get_next_tx_id(Tx);
+
+get_next_tx_id(?IS_SS = SS) ->
+ get_next_tx_id(?GET_TX(SS)).
+
+
is_read_only(?IS_TX = Tx) ->
erlfdb_nif:transaction_is_read_only(Tx);
diff --git a/src/erlfdb_nif.erl b/src/erlfdb_nif.erl
index 478ba09..546d055 100644
--- a/src/erlfdb_nif.erl
+++ b/src/erlfdb_nif.erl
@@ -55,6 +55,7 @@
transaction_reset/1,
transaction_cancel/1,
transaction_add_conflict_range/4,
+ transaction_get_next_tx_id/1,
transaction_is_read_only/1,
get_error/1,
@@ -440,6 +441,11 @@
erlfdb_transaction_add_conflict_range(Tx, StartKey, EndKey, ConflictType).
+-spec transaction_get_next_tx_id(transaction()) -> non_neg_integer().
+transaction_get_next_tx_id({erlfdb_transaction, Tx}) ->
+ erlfdb_transaction_get_next_tx_id(Tx).
+
+
-spec transaction_is_read_only(transaction()) -> true | false.
transaction_is_read_only({erlfdb_transaction, Tx}) ->
erlfdb_transaction_is_read_only(Tx).
@@ -587,6 +593,7 @@
_EndKey,
_Type
) -> ?NOT_LOADED.
+erlfdb_transaction_get_next_tx_id(_Transaction) -> ?NOT_LOADED.
erlfdb_transaction_is_read_only(_Transaction) -> ?NOT_LOADED.
diff --git a/test/erlfdb_05_get_next_tx_id_test.erl b/test/erlfdb_05_get_next_tx_id_test.erl
new file mode 100644
index 0000000..c8b2d8d
--- /dev/null
+++ b/test/erlfdb_05_get_next_tx_id_test.erl
@@ -0,0 +1,25 @@
+% Licensed under the Apache License, Version 2.0 (the "License"); you may not
+% use this file except in compliance with the License. You may obtain a copy of
+% the License at
+%
+% http://www.apache.org/licenses/LICENSE-2.0
+%
+% Unless required by applicable law or agreed to in writing, software
+% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+% License for the specific language governing permissions and limitations under
+% the License.
+
+-module(erlfdb_05_get_next_tx_id_test).
+
+-include_lib("eunit/include/eunit.hrl").
+
+
+get_tx_id_test() ->
+ Db = erlfdb_util:get_test_db(),
+ erlfdb:transactional(Db, fun(Tx) ->
+ lists:foreach(fun(I) ->
+ ?assertEqual(I, erlfdb:get_next_tx_id(Tx))
+ end, lists:seq(0, 65535)),
+ ?assertError(badarg, erlfdb:get_next_tx_id(Tx))
+ end).