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).