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/17 18:51:22 UTC

[couchdb] branch prototype/rfc-001-revision-metadata-model updated (44bc553 -> ef5270f)

This is an automated email from the ASF dual-hosted git repository.

davisp pushed a change to branch prototype/rfc-001-revision-metadata-model
in repository https://gitbox.apache.org/repos/asf/couchdb.git.


    from 44bc553  Pass a TxDb to fold functions
     new 8f5a5d2  Stop the test cluster on shutdown
     new 4aedb4d  Update batches with parallel reads
     new e083075  Add more trace tests
     new ef5270f  Fix parallel doc updates

The 4 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 src/fabric/src/fabric2_app.erl                     |   4 +
 src/fabric/src/fabric2_db.erl                      | 103 ++++++++++++++++++---
 src/fabric/src/fabric2_fdb.erl                     |  37 +++++---
 .../test/fabric2_trace_db_create_tests.erl}        |  46 +++++----
 .../test/fabric2_trace_db_delete_tests.erl}        |  49 ++++++----
 ...e_tests.erl => fabric2_trace_db_open_tests.erl} |  47 ++--------
 src/fabric/test/fabric2_trace_doc_create_tests.erl |  29 +++---
 7 files changed, 207 insertions(+), 108 deletions(-)
 copy src/{mem3/test/mem3_sync_security_test.erl => fabric/test/fabric2_trace_db_create_tests.erl} (56%)
 copy src/{mem3/test/mem3_sync_security_test.erl => fabric/test/fabric2_trace_db_delete_tests.erl} (50%)
 copy src/fabric/test/{fabric2_trace_doc_create_tests.erl => fabric2_trace_db_open_tests.erl} (51%)


[couchdb] 04/04: Fix parallel doc updates

Posted by da...@apache.org.
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 ef5270f4034bb752ac5bc98bbccc8b60de7227c7
Author: Paul J. Davis <pa...@gmail.com>
AuthorDate: Fri May 17 13:51:01 2019 -0500

    Fix parallel doc updates
---
 src/fabric/src/fabric2_db.erl  | 79 ++++++++++++++++++++++++------------------
 src/fabric/src/fabric2_fdb.erl |  2 +-
 2 files changed, 46 insertions(+), 35 deletions(-)

diff --git a/src/fabric/src/fabric2_db.erl b/src/fabric/src/fabric2_db.erl
index c2a19ba..f82d2de 100644
--- a/src/fabric/src/fabric2_db.erl
+++ b/src/fabric/src/fabric2_db.erl
@@ -489,7 +489,7 @@ update_docs(Db, Docs, Options) ->
                 fabric2_fdb:transactional(Db, fun(TxDb) ->
                     update_doc_int(TxDb, Doc, Options)
                 end)
-            end)
+            end, Docs)
     end,
     Status = lists:foldl(fun(Resp, Acc) ->
         case Resp of
@@ -648,7 +648,6 @@ get_members(SecProps) ->
     end.
 
 
-% TODO: Handle _local docs separately.
 update_doc_int(#{} = Db, #doc{} = Doc, Options) ->
     IsLocal = case Doc#doc.id of
         <<?LOCAL_DOC_PREFIX, _/binary>> -> true;
@@ -668,43 +667,36 @@ update_doc_int(#{} = Db, #doc{} = Doc, Options) ->
 
 update_docs_interactive(Db, Docs0, Options) ->
     Docs = tag_docs(Docs0),
-    Futures = lists:foldl(fun(Doc, Acc) ->
-        #doc{
-            id = DocId,
-            deleted = Deleted
-        } = Doc,
-        case DocId of
-            <<?LOCAL_DOC_PREFIX, _/binary>> ->
-                Acc;
-            _ ->
-                NumRevs = if Deleted -> 2; true -> 1 end,
-                Future = fabric2_fdb:get_winning_revs_future(Db, DocId, NumRevs),
-                DocTag = doc_tag(Doc),
-                Acc#{DocTag => Future}
-        end
-    end, #{}, Docs),
-    {Result, _} = lists:mapfoldl(fun(#doc{id = DocId} = Doc, Acc) ->
-        case DocId of
-            <<?LOCAL_DOC_PREFIX, _/binary>> ->
-                {update_local_doc(Db, Doc, Options), Acc};
-            _ ->
-                case lists:member(DocId, Acc) of
-                    false ->
-                        Future = maps:get(doc_tag(Doc), Futures),
-                        case update_doc_interactive(Db, Doc, Future, Options) of
-                            {ok, _} = Resp ->
-                                {Resp, [DocId | Acc]};
-                            _ = Resp ->
-                                {Resp, Acc}
-                        end;
-                    true ->
-                        {{error, conflict}, Acc}
-                end
+    Futures = get_winning_rev_futures(Db, Docs),
+    {Result, _} = lists:mapfoldl(fun(Doc, SeenIds) ->
+        try
+            update_docs_interactive(Db, Doc, Options, Futures, SeenIds)
+        catch throw:{?MODULE, Return} ->
+            {Return, SeenIds}
         end
     end, [], Docs),
     Result.
 
 
+update_docs_interactive(Db, #doc{id = <<?LOCAL_DOC_PREFIX, _/binary>>} = Doc,
+        Options, Futures, SeenIds) ->
+    {update_local_doc(Db, Doc, Options), SeenIds};
+
+update_docs_interactive(Db, Doc, Options, Futures, SeenIds) ->
+    case lists:member(Doc#doc.id, SeenIds) of
+        true ->
+            {{error, conflict}, SeenIds};
+        false ->
+            Future = maps:get(doc_tag(Doc), Futures),
+            case update_doc_interactive(Db, Doc, Future, Options) of
+                {ok, _} = Resp ->
+                    {Resp, [Doc#doc.id | SeenIds]};
+                _ = Resp ->
+                    {Resp, SeenIds}
+            end
+    end.
+
+
 update_doc_interactive(Db, Doc0, Options) ->
     % Get the current winning revision. This is needed
     % regardless of which branch we're updating. The extra
@@ -925,6 +917,25 @@ update_local_doc(Db, Doc0, _Options) ->
     {ok, {0, integer_to_binary(Rev)}}.
 
 
+get_winning_rev_futures(Db, Docs) ->
+    lists:foldl(fun(Doc, Acc) ->
+        #doc{
+            id = DocId,
+            deleted = Deleted
+        } = Doc,
+        IsLocal = case DocId of
+            <<?LOCAL_DOC_PREFIX, _/binary>> -> true;
+            _ -> false
+        end,
+        if IsLocal -> Acc; true ->
+            NumRevs = if Deleted -> 2; true -> 1 end,
+            Future = fabric2_fdb:get_winning_revs_future(Db, DocId, NumRevs),
+            DocTag = doc_tag(Doc),
+            Acc#{DocTag => Future}
+        end
+    end, #{}, Docs).
+
+
 prep_and_validate(Db, Doc, PrevRevInfo) ->
     HasStubs = couch_doc:has_stubs(Doc),
     HasVDUs = [] /= maps:get(validate_doc_update_funs, Db),
diff --git a/src/fabric/src/fabric2_fdb.erl b/src/fabric/src/fabric2_fdb.erl
index 0374cff..e49f9be 100644
--- a/src/fabric/src/fabric2_fdb.erl
+++ b/src/fabric/src/fabric2_fdb.erl
@@ -381,7 +381,7 @@ get_winning_revs_wait(#{} = Db, Future) ->
     #{
         db_prefix := DbPrefix
     } = ensure_current(Db),
-    {Rows, _, false} = erlfdb:wait(Future),
+    {Rows, _, _} = erlfdb:wait(Future),
     lists:map(fun({K, V}) ->
         Key = erlfdb_tuple:unpack(K, DbPrefix),
         Val = erlfdb_tuple:unpack(V),


[couchdb] 02/04: Update batches with parallel reads

Posted by da...@apache.org.
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 4aedb4d2adc7f296700974bbe4e05fddf4562a25
Author: Paul J. Davis <pa...@gmail.com>
AuthorDate: Tue May 14 11:05:37 2019 -0500

    Update batches with parallel reads
---
 src/fabric/src/fabric2_db.erl  | 90 ++++++++++++++++++++++++++++++++++++------
 src/fabric/src/fabric2_fdb.erl | 37 +++++++++++------
 2 files changed, 101 insertions(+), 26 deletions(-)

diff --git a/src/fabric/src/fabric2_db.erl b/src/fabric/src/fabric2_db.erl
index d5842e8..c2a19ba 100644
--- a/src/fabric/src/fabric2_db.erl
+++ b/src/fabric/src/fabric2_db.erl
@@ -479,21 +479,28 @@ update_docs(Db, Docs) ->
 
 
 update_docs(Db, Docs, Options) ->
-    {Resps0, Status} = lists:mapfoldl(fun(Doc, Acc) ->
-        fabric2_fdb:transactional(Db, fun(TxDb) ->
-            case update_doc_int(TxDb, Doc, Options) of
-                {ok, _} = Resp ->
-                    {Resp, Acc};
-                Resp ->
-                    {Resp, error}
-            end
-        end)
-    end, ok, Docs),
+    Resps0 = case lists:member(replicated_changes, Options) of
+        false ->
+            fabric2_fdb:transactional(Db, fun(TxDb) ->
+                update_docs_interactive(TxDb, Docs, Options)
+            end);
+        true ->
+            lists:map(fun(Doc) ->
+                fabric2_fdb:transactional(Db, fun(TxDb) ->
+                    update_doc_int(TxDb, Doc, Options)
+                end)
+            end)
+    end,
+    Status = lists:foldl(fun(Resp, Acc) ->
+        case Resp of
+            {ok, _} -> Acc;
+            _ -> error
+        end
+    end, ok, Resps0),
     Resps1 = case lists:member(replicated_changes, Options) of
         true -> [R || R <- Resps0, R /= {ok, []}];
         false -> Resps0
     end,
-    %io:format(standard_error, "~nRESPS: ~p :: ~p~n~n", [Resps0, Resps1]),
     {Status, Resps1}.
 
 
@@ -659,14 +666,58 @@ update_doc_int(#{} = Db, #doc{} = Doc, Options) ->
     end.
 
 
-update_doc_interactive(Db, Doc0, _Options) ->
+update_docs_interactive(Db, Docs0, Options) ->
+    Docs = tag_docs(Docs0),
+    Futures = lists:foldl(fun(Doc, Acc) ->
+        #doc{
+            id = DocId,
+            deleted = Deleted
+        } = Doc,
+        case DocId of
+            <<?LOCAL_DOC_PREFIX, _/binary>> ->
+                Acc;
+            _ ->
+                NumRevs = if Deleted -> 2; true -> 1 end,
+                Future = fabric2_fdb:get_winning_revs_future(Db, DocId, NumRevs),
+                DocTag = doc_tag(Doc),
+                Acc#{DocTag => Future}
+        end
+    end, #{}, Docs),
+    {Result, _} = lists:mapfoldl(fun(#doc{id = DocId} = Doc, Acc) ->
+        case DocId of
+            <<?LOCAL_DOC_PREFIX, _/binary>> ->
+                {update_local_doc(Db, Doc, Options), Acc};
+            _ ->
+                case lists:member(DocId, Acc) of
+                    false ->
+                        Future = maps:get(doc_tag(Doc), Futures),
+                        case update_doc_interactive(Db, Doc, Future, Options) of
+                            {ok, _} = Resp ->
+                                {Resp, [DocId | Acc]};
+                            _ = Resp ->
+                                {Resp, Acc}
+                        end;
+                    true ->
+                        {{error, conflict}, Acc}
+                end
+        end
+    end, [], Docs),
+    Result.
+
+
+update_doc_interactive(Db, Doc0, Options) ->
     % Get the current winning revision. This is needed
     % regardless of which branch we're updating. The extra
     % revision we're grabbing is an optimization to
     % save us a round trip if we end up deleting
     % the winning revision branch.
     NumRevs = if Doc0#doc.deleted -> 2; true -> 1 end,
-    RevInfos = fabric2_fdb:get_winning_revs(Db, Doc0#doc.id, NumRevs),
+    Future = fabric2_fdb:get_winning_revs_future(Db, Doc0#doc.id, NumRevs),
+    update_doc_interactive(Db, Doc0, Future, Options).
+
+
+update_doc_interactive(Db, Doc0, Future, _Options) ->
+    RevInfos = fabric2_fdb:get_winning_revs_wait(Db, Future),
     {Winner, SecondPlace} = case RevInfos of
         [] -> {not_found, not_found};
         [WRI] -> {WRI, not_found};
@@ -980,3 +1031,16 @@ doc_to_revid(#doc{revs = Revs}) ->
         {0, []} -> {0, <<>>};
         {RevPos, [Rev | _]} -> {RevPos, Rev}
     end.
+
+
+tag_docs([]) ->
+    [];
+tag_docs([#doc{meta = Meta} = Doc | Rest]) ->
+    NewDoc = Doc#doc{
+        meta = [{ref, make_ref()} | Meta]
+    },
+    [NewDoc | tag_docs(Rest)].
+
+
+doc_tag(#doc{meta = Meta}) ->
+    fabric2_util:get_value(ref, Meta).
diff --git a/src/fabric/src/fabric2_fdb.erl b/src/fabric/src/fabric2_fdb.erl
index acb8b82..0374cff 100644
--- a/src/fabric/src/fabric2_fdb.erl
+++ b/src/fabric/src/fabric2_fdb.erl
@@ -35,6 +35,8 @@
 
     get_all_revs/2,
     get_winning_revs/3,
+    get_winning_revs_future/3,
+    get_winning_revs_wait/2,
     get_non_deleted_rev/3,
 
     get_doc_body/3,
@@ -80,9 +82,11 @@ do_transaction(Fun, LayerPrefix) when is_function(Fun, 1) ->
     Db = get_db_handle(),
     try
         erlfdb:transactional(Db, fun(Tx) ->
-            case get('erlfdb_trace') of
-                true -> erlfdb:set_option(Tx, transaction_logging_enable);
-                _ -> ok
+            case get(erlfdb_trace) of
+                Name when is_binary(Name) ->
+                    erlfdb:set_option(Tx, transaction_logging_enable, Name);
+                _ ->
+                    ok
             end,
             case is_transaction_applied(Tx) of
                 true ->
@@ -357,7 +361,12 @@ get_all_revs(#{} = Db, DocId) ->
     end, erlfdb:wait(Future)).
 
 
-get_winning_revs(#{} = Db, DocId, NumRevs) ->
+get_winning_revs(Db, DocId, NumRevs) ->
+    Future = get_winning_revs_future(Db, DocId, NumRevs),
+    get_winning_revs_wait(Db, Future).
+
+
+get_winning_revs_future(#{} = Db, DocId, NumRevs) ->
     #{
         tx := Tx,
         db_prefix := DbPrefix
@@ -365,12 +374,19 @@ get_winning_revs(#{} = Db, DocId, NumRevs) ->
 
     {StartKey, EndKey} = erlfdb_tuple:range({?DB_REVS, DocId}, DbPrefix),
     Options = [{reverse, true}, {limit, NumRevs}],
-    Future = erlfdb:get_range(Tx, StartKey, EndKey, Options),
+    erlfdb:get_range_raw(Tx, StartKey, EndKey, Options).
+
+
+get_winning_revs_wait(#{} = Db, Future) ->
+    #{
+        db_prefix := DbPrefix
+    } = ensure_current(Db),
+    {Rows, _, false} = erlfdb:wait(Future),
     lists:map(fun({K, V}) ->
         Key = erlfdb_tuple:unpack(K, DbPrefix),
         Val = erlfdb_tuple:unpack(V),
         fdb_to_revinfo(Key, Val)
-    end, erlfdb:wait(Future)).
+    end, Rows).
 
 
 get_non_deleted_rev(#{} = Db, DocId, RevId) ->
@@ -903,7 +919,6 @@ get_since_seq(Seq) when is_binary(Seq), size(Seq) == 24 ->
     SeqVS.
 
 
-
 get_db_handle() ->
     case get(?PDICT_DB_KEY) of
         undefined ->
@@ -986,11 +1001,7 @@ get_transaction_id(Tx, LayerPrefix) ->
     end.
 
 
-new_versionstamp(_Tx) ->
-    % Eventually we'll have a erlfdb:get_next_tx_id(Tx)
-    % that will return a monotonically incrementing
-    % integer from 0 to 65535. For now we just hardcode
-    % 0 since we're not doing multiple docs per batch.
-    TxId = 0,
+new_versionstamp(Tx) ->
+    TxId = erlfdb:get_next_tx_id(Tx),
     {versionstamp, 16#FFFFFFFFFFFFFFFF, 16#FFFF, TxId}.
 


[couchdb] 01/04: Stop the test cluster on shutdown

Posted by da...@apache.org.
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 8f5a5d210d3996c3a4487526aca551c96596b647
Author: Paul J. Davis <pa...@gmail.com>
AuthorDate: Tue May 14 11:05:05 2019 -0500

    Stop the test cluster on shutdown
---
 src/fabric/src/fabric2_app.erl | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/src/fabric/src/fabric2_app.erl b/src/fabric/src/fabric2_app.erl
index 9becf8b..da95acb 100644
--- a/src/fabric/src/fabric2_app.erl
+++ b/src/fabric/src/fabric2_app.erl
@@ -25,4 +25,8 @@ start(_Type, StartArgs) ->
 
 
 stop(_State) ->
+    case application:get_env(erlfdb, test_cluster_pid) of
+        {ok, Pid} -> Pid ! close;
+        _ -> ok
+    end,
     ok.


[couchdb] 03/04: Add more trace tests

Posted by da...@apache.org.
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 e083075431c67958013060e163aa780ee6924a64
Author: Paul J. Davis <pa...@gmail.com>
AuthorDate: Tue May 14 11:05:55 2019 -0500

    Add more trace tests
    
    These are useful when attempting to generate FoundationDB trace files
    for later analysis. They're broken out to be a simple of an operation as
    possible to avoid generate huge trace files of the larger more
    complicated tests.
---
 src/fabric/test/fabric2_trace_db_create_tests.erl  | 46 ++++++++++++++++++++
 src/fabric/test/fabric2_trace_db_delete_tests.erl  | 49 ++++++++++++++++++++++
 ...e_tests.erl => fabric2_trace_db_open_tests.erl} | 47 ++++-----------------
 src/fabric/test/fabric2_trace_doc_create_tests.erl | 29 ++++++++-----
 4 files changed, 122 insertions(+), 49 deletions(-)

diff --git a/src/fabric/test/fabric2_trace_db_create_tests.erl b/src/fabric/test/fabric2_trace_db_create_tests.erl
new file mode 100644
index 0000000..09cc863
--- /dev/null
+++ b/src/fabric/test/fabric2_trace_db_create_tests.erl
@@ -0,0 +1,46 @@
+% 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_db_create_tests).
+
+
+-include_lib("couch/include/couch_db.hrl").
+-include_lib("couch/include/couch_eunit.hrl").
+-include_lib("eunit/include/eunit.hrl").
+
+
+trace_test_() ->
+    {
+        "Trace operation",
+        {
+            setup,
+            fun setup/0,
+            fun cleanup/1,
+            [
+                fun create_db/0
+            ]
+        }
+    }.
+
+
+setup() ->
+    put(erlfdb_trace, "starting fabric"),
+    test_util:start_couch([fabric]).
+
+
+cleanup(Ctx) ->
+    test_util:stop_couch(Ctx).
+
+
+create_db() ->
+    put(erlfdb_trace, <<"create db">>),
+    {ok, _Db} = fabric2_db:create(?tempdb(), [{user_ctx, ?ADMIN_USER}]).
diff --git a/src/fabric/test/fabric2_trace_db_delete_tests.erl b/src/fabric/test/fabric2_trace_db_delete_tests.erl
new file mode 100644
index 0000000..ddbb2c8
--- /dev/null
+++ b/src/fabric/test/fabric2_trace_db_delete_tests.erl
@@ -0,0 +1,49 @@
+% 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_db_delete_tests).
+
+
+-include_lib("couch/include/couch_db.hrl").
+-include_lib("couch/include/couch_eunit.hrl").
+-include_lib("eunit/include/eunit.hrl").
+
+
+trace_test_() ->
+    {
+        "Trace operation",
+        {
+            setup,
+            fun setup/0,
+            fun cleanup/1,
+            {with, [
+                fun delete_db/1
+            ]}
+        }
+    }.
+
+
+setup() ->
+    put(erlfdb_trace, "starting fabric"),
+    Ctx = test_util:start_couch([fabric]),
+    {ok, Db} = fabric2_db:create(?tempdb(), [{user_ctx, ?ADMIN_USER}]),
+    {Db, Ctx}.
+
+
+cleanup({_Db, Ctx}) ->
+    test_util:stop_couch(Ctx).
+
+
+delete_db({Db, _}) ->
+    put(erlfdb_trace, <<"delete db">>),
+    fabric2_server:remove(fabric2_db:name(Db)),
+    ok = fabric2_db:delete(fabric2_db:name(Db), []).
diff --git a/src/fabric/test/fabric2_trace_doc_create_tests.erl b/src/fabric/test/fabric2_trace_db_open_tests.erl
similarity index 51%
copy from src/fabric/test/fabric2_trace_doc_create_tests.erl
copy to src/fabric/test/fabric2_trace_db_open_tests.erl
index 279533b..71e3301 100644
--- a/src/fabric/test/fabric2_trace_doc_create_tests.erl
+++ b/src/fabric/test/fabric2_trace_db_open_tests.erl
@@ -10,7 +10,7 @@
 % License for the specific language governing permissions and limitations under
 % the License.
 
--module(fabric2_trace_doc_create_tests).
+-module(fabric2_trace_db_open_tests).
 
 
 -include_lib("couch/include/couch_db.hrl").
@@ -18,23 +18,22 @@
 -include_lib("eunit/include/eunit.hrl").
 
 
-doc_crud_test_() ->
+trace_test_() ->
     {
-        "Test document CRUD operations",
+        "Trace operation",
         {
             setup,
             fun setup/0,
             fun cleanup/1,
             {with, [
-                fun create_new_doc/1,
-                fun create_two_docs/1,
-                fun create_50_docs/1
+                fun open_db/1
             ]}
         }
     }.
 
 
 setup() ->
+    put(erlfdb_trace, "starting fabric"),
     Ctx = test_util:start_couch([fabric]),
     {ok, Db} = fabric2_db:create(?tempdb(), [{user_ctx, ?ADMIN_USER}]),
     {Db, Ctx}.
@@ -45,35 +44,7 @@ cleanup({Db, Ctx}) ->
     test_util:stop_couch(Ctx).
 
 
-create_new_doc({Db, _}) ->
-    put(erlfdb_trace, true),
-    Doc = #doc{
-        id = fabric2_util:uuid(),
-        body = {[{<<"foo">>, <<"bar">>}]}
-    },
-    {ok, _} = fabric2_db:update_doc(Db, Doc).
-
-
-create_two_docs({Db, _}) ->
-    put(erlfdb_trace, true),
-    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, _}) ->
-    put(erlfdb_trace, true),
-    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).
-
+open_db({Db, _}) ->
+    put(erlfdb_trace, <<"open db">>),
+    fabric2_server:remove(fabric2_db:name(Db)),
+    {ok, _Db} = fabric2_db:open(fabric2_db:name(Db), [{user_ctx, ?ADMIN_USER}]).
diff --git a/src/fabric/test/fabric2_trace_doc_create_tests.erl b/src/fabric/test/fabric2_trace_doc_create_tests.erl
index 279533b..1e0b47c 100644
--- a/src/fabric/test/fabric2_trace_doc_create_tests.erl
+++ b/src/fabric/test/fabric2_trace_doc_create_tests.erl
@@ -46,7 +46,7 @@ cleanup({Db, Ctx}) ->
 
 
 create_new_doc({Db, _}) ->
-    put(erlfdb_trace, true),
+    put(erlfdb_trace, <<"one doc">>),
     Doc = #doc{
         id = fabric2_util:uuid(),
         body = {[{<<"foo">>, <<"bar">>}]}
@@ -55,7 +55,7 @@ create_new_doc({Db, _}) ->
 
 
 create_two_docs({Db, _}) ->
-    put(erlfdb_trace, true),
+    put(erlfdb_trace, <<"two docs">>),
     Doc1 = #doc{
         id = fabric2_util:uuid(),
         body = {[{<<"bam">>, <<"baz">>}]}
@@ -68,12 +68,19 @@ create_two_docs({Db, _}) ->
 
 
 create_50_docs({Db, _}) ->
-    put(erlfdb_trace, true),
-    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).
-
+    lists:foreach(fun(_) ->
+        spawn_monitor(fun() ->
+            Name = io_lib:format("50 docs : ~w", [self()]),
+            put(erlfdb_trace, iolist_to_binary(Name)),
+            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)
+        end)
+    end, lists:seq(1, 5)),
+    lists:foreach(fun(_) ->
+        receive {'DOWN', _, _, _, _} -> ok end
+    end, lists:seq(1, 5)).