You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by da...@apache.org on 2019/05/02 14:42:25 UTC
[couchdb] 01/02: Tests
This is an automated email from the ASF dual-hosted git repository.
davisp pushed a commit to branch prototype/rfc-001-revision-metadata-model
in repository https://gitbox.apache.org/repos/asf/couchdb.git
commit a9efd04d6d65979b36922e73d0737237e3c96f50
Author: Paul J. Davis <pa...@gmail.com>
AuthorDate: Thu May 2 08:36:04 2019 -0500
Tests
---
src/fabric/src/fabric2_db.erl | 18 +++--
src/fabric/src/fabric2_fdb.erl | 46 +++++++------
src/fabric/src/fabric2_txids.erl | 9 ++-
src/fabric/test/fabric2_trace_doc_create_tests.erl | 76 ++++++++++++++++++++++
4 files changed, 120 insertions(+), 29 deletions(-)
diff --git a/src/fabric/src/fabric2_db.erl b/src/fabric/src/fabric2_db.erl
index c276ae2..d5842e8 100644
--- a/src/fabric/src/fabric2_db.erl
+++ b/src/fabric/src/fabric2_db.erl
@@ -153,7 +153,7 @@ create(DbName, Options) ->
case Result of
#{} = Db ->
ok = fabric2_server:store(Db),
- {ok, Db#{tx => undefined}};
+ {ok, Db#{tx := undefined}};
Error ->
Error
end.
@@ -164,11 +164,17 @@ open(DbName, Options) ->
#{} = Db ->
{ok, maybe_set_user_ctx(Db, Options)};
undefined ->
- fabric2_fdb:transactional(DbName, Options, fun(TxDb) ->
- Opened = fabric2_fdb:open(TxDb, Options),
- ok = fabric2_server:store(Opened),
- {ok, Opened#{tx => undefined}}
- end)
+ Result = fabric2_fdb:transactional(DbName, Options, fun(TxDb) ->
+ fabric2_fdb:open(TxDb, Options)
+ end),
+ % Cache outside the transaction retry loop
+ case Result of
+ #{} = Db ->
+ ok = fabric2_server:store(Db),
+ {ok, Db#{tx := undefined}};
+ Error ->
+ Error
+ end
end.
diff --git a/src/fabric/src/fabric2_fdb.erl b/src/fabric/src/fabric2_fdb.erl
index 769a5a8..3666268 100644
--- a/src/fabric/src/fabric2_fdb.erl
+++ b/src/fabric/src/fabric2_fdb.erl
@@ -56,20 +56,8 @@
-include("fabric2.hrl").
-transactional(Fun) when is_function(Fun, 1) ->
- Db = get_db_handle(),
- try
- erlfdb:transactional(Db, fun(Tx) ->
- case is_transaction_applied(Tx) of
- true ->
- get_previous_transaction_result();
- false ->
- execute_transaction(Tx, Fun)
- end
- end)
- after
- clear_transaction()
- end.
+transactional(Fun) ->
+ do_transaction(Fun, undefined).
transactional(DbName, Options, Fun) when is_binary(DbName) ->
@@ -79,14 +67,32 @@ transactional(DbName, Options, Fun) when is_binary(DbName) ->
transactional(#{tx := undefined} = Db, Fun) ->
- transactional(fun(Tx) ->
+ #{layer_prefix := LayerPrefix} = Db,
+ do_transaction(fun(Tx) ->
Fun(Db#{tx => Tx})
- end);
+ end, LayerPrefix);
transactional(#{tx := {erlfdb_transaction, _}} = Db, Fun) ->
Fun(Db).
+do_transaction(Fun, LayerPrefix) when is_function(Fun, 1) ->
+ Db = get_db_handle(),
+ try
+ erlfdb:transactional(Db, fun(Tx) ->
+ erlfdb:set_option(Tx, transaction_logging_enable),
+ case is_transaction_applied(Tx) of
+ true ->
+ get_previous_transaction_result();
+ false ->
+ execute_transaction(Tx, Fun, LayerPrefix)
+ end
+ end)
+ after
+ clear_transaction()
+ end.
+
+
create(#{} = Db0, Options) ->
#{
name := DbName,
@@ -936,13 +942,13 @@ get_previous_transaction_result() ->
get(?PDICT_TX_RES_KEY).
-execute_transaction(Tx, Fun) ->
+execute_transaction(Tx, Fun, LayerPrefix) ->
Result = Fun(Tx),
case erlfdb:is_read_only(Tx) of
true ->
ok;
false ->
- erlfdb:set(Tx, get_transaction_id(Tx), <<>>),
+ erlfdb:set(Tx, get_transaction_id(Tx, LayerPrefix), <<>>),
put(?PDICT_TX_RES_KEY, Result)
end,
Result.
@@ -966,10 +972,10 @@ transaction_id_exists(Tx) ->
erlfdb:wait(erlfdb:get(Tx, get(?PDICT_TX_ID_KEY))) == <<>>.
-get_transaction_id(Tx) ->
+get_transaction_id(Tx, LayerPrefix) ->
case get(?PDICT_TX_ID_KEY) of
undefined ->
- TxId = fabric2_txids:create(Tx),
+ TxId = fabric2_txids:create(Tx, LayerPrefix),
put(?PDICT_TX_ID_KEY, TxId),
TxId;
TxId when is_binary(TxId) ->
diff --git a/src/fabric/src/fabric2_txids.erl b/src/fabric/src/fabric2_txids.erl
index a9d6390..bbb8bdf 100644
--- a/src/fabric/src/fabric2_txids.erl
+++ b/src/fabric/src/fabric2_txids.erl
@@ -17,7 +17,7 @@
-export([
start_link/0,
- create/1,
+ create/2,
remove/1
]).
@@ -43,13 +43,16 @@ start_link() ->
gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
-create(Tx) ->
+create(Tx, undefined) ->
Root = erlfdb_directory:root(),
CouchDB = erlfdb_directory:create_or_open(Tx, Root, [<<"couchdb">>]),
Prefix = erlfdb_directory:get_name(CouchDB),
+ create(Tx, Prefix);
+
+create(_Tx, LayerPrefix) ->
{Mega, Secs, Micro} = os:timestamp(),
Key = {?TX_IDS, Mega, Secs, Micro, fabric2_util:uuid()},
- erlfdb_tuple:pack(Key, Prefix).
+ erlfdb_tuple:pack(Key, LayerPrefix).
remove(TxId) when is_binary(TxId) ->
diff --git a/src/fabric/test/fabric2_trace_doc_create_tests.erl b/src/fabric/test/fabric2_trace_doc_create_tests.erl
new file mode 100644
index 0000000..21b9738
--- /dev/null
+++ b/src/fabric/test/fabric2_trace_doc_create_tests.erl
@@ -0,0 +1,76 @@
+% 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(fabric2_trace_doc_create_tests).
+
+
+-include_lib("couch/include/couch_db.hrl").
+-include_lib("couch/include/couch_eunit.hrl").
+-include_lib("eunit/include/eunit.hrl").
+
+
+doc_crud_test_() ->
+ {
+ "Test document CRUD operations",
+ {
+ setup,
+ fun setup/0,
+ fun cleanup/1,
+ {with, [
+ fun create_new_doc/1,
+ fun create_two_docs/1,
+ fun create_50_docs/1
+ ]}
+ }
+ }.
+
+
+setup() ->
+ Ctx = test_util:start_couch([fabric]),
+ {ok, Db} = fabric2_db:create(?tempdb(), [{user_ctx, ?ADMIN_USER}]),
+ {Db, Ctx}.
+
+
+cleanup({Db, Ctx}) ->
+ ok = fabric2_db:delete(fabric2_db:name(Db), []),
+ test_util:stop_couch(Ctx).
+
+
+create_new_doc({Db, _}) ->
+ Doc = #doc{
+ id = fabric2_util:uuid(),
+ body = {[{<<"foo">>, <<"bar">>}]}
+ },
+ {ok, _} = fabric2_db:update_doc(Db, Doc).
+
+
+create_two_docs({Db, _}) ->
+ Doc1 = #doc{
+ id = fabric2_util:uuid(),
+ body = {[{<<"bam">>, <<"baz">>}]}
+ },
+ Doc2 = #doc{
+ id = fabric2_util:uuid(),
+ body = {[{<<"bang">>, <<"bargle">>}]}
+ },
+ {ok, _} = fabric2_db:update_docs(Db, [Doc1, Doc2]).
+
+
+create_50_docs({Db, _}) ->
+ Docs = lists:map(fun(Val) ->
+ #doc{
+ id = fabric2_util:uuid(),
+ body = {[{<<"value">>, Val}]}
+ }
+ end, lists:seq(1, 50)),
+ {ok, _} = fabric2_db:update_docs(Db, Docs).
+