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/04/18 14:58:57 UTC

[couchdb] branch prototype/rfc-001-revision-metadata-model updated: WIP cleanup txid work

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


The following commit(s) were added to refs/heads/prototype/rfc-001-revision-metadata-model by this push:
     new e1fdb6e  WIP cleanup txid work
e1fdb6e is described below

commit e1fdb6ed37b728786bf68c117d98eb3899d29ab1
Author: Paul J. Davis <pa...@gmail.com>
AuthorDate: Thu Apr 18 09:57:29 2019 -0500

    WIP cleanup txid work
---
 src/fabric/src/fabric2_fdb.erl                     | 86 ++++++++++------------
 src/fabric/src/fabric2_sup.erl                     |  4 +-
 ...{fabric2_txid_cleaner.erl => fabric2_txids.erl} | 12 ++-
 3 files changed, 52 insertions(+), 50 deletions(-)

diff --git a/src/fabric/src/fabric2_fdb.erl b/src/fabric/src/fabric2_fdb.erl
index adc0a3a..9215000 100644
--- a/src/fabric/src/fabric2_fdb.erl
+++ b/src/fabric/src/fabric2_fdb.erl
@@ -59,10 +59,15 @@ transactional(Fun) when is_function(Fun, 1) ->
     Db = get_db_handle(),
     try
         erlfdb:transactional(Db, fun(Tx) ->
-            tx_wrap(Tx, Fun)
+            case is_transaction_applied(Tx) of
+                true ->
+                    get_previous_transaction_result();
+                false ->
+                    execute_transaction(Tx, Fun)
+            end
         end)
     after
-        tx_clear()
+        clear_transaction()
     end.
 
 
@@ -81,13 +86,12 @@ transactional(#{tx := {erlfdb_transaction, _}} = Db, Fun) ->
     Fun(Db).
 
 
-create(#{} = Db, Options) ->
-    require_transaction(Db),
+create(#{} = Db0, Options) ->
     #{
         name := DbName,
         tx := Tx,
         layer_prefix := LayerPrefix
-    } = Db,
+    } = Db = ensure_current(Db0),
 
     % Eventually DbPrefix will be HCA allocated. For now
     % we're just using the DbName so that debugging is easier.
@@ -113,12 +117,10 @@ create(#{} = Db, Options) ->
     end, Defaults),
 
     UserCtx = fabric2_util:get_value(user_ctx, Options, #user_ctx{}),
-    Version = erlfdb:wait(erlfdb:get(Tx, ?METADATA_VERSION_KEY)),
 
     Db#{
         uuid => UUID,
         db_prefix => DbPrefix,
-        md_version => Version,
 
         revs_limit => 1000,
         security_doc => {[]},
@@ -134,12 +136,11 @@ create(#{} = Db, Options) ->
 
 
 open(#{} = Db0, Options) ->
-    require_transaction(Db0),
     #{
         name := DbName,
         tx := Tx,
         layer_prefix := LayerPrefix
-    } = Db0,
+    } = Db1 = ensure_current(Db0),
 
     DbKey = erlfdb_tuple:pack({?ALL_DBS, DbName}, LayerPrefix),
     DbPrefix = case erlfdb:wait(erlfdb:get(Tx, DbKey)) of
@@ -148,11 +149,9 @@ open(#{} = Db0, Options) ->
     end,
 
     UserCtx = fabric2_util:get_value(user_ctx, Options, #user_ctx{}),
-    Version = erlfdb:wait(erlfdb:get(Tx, ?METADATA_VERSION_KEY)),
 
-    Db1 = Db0#{
+    Db2 = Db1#{
         db_prefix => DbPrefix,
-        md_version => Version,
 
         revs_limit => 1000,
         security_doc => {[]},
@@ -176,7 +175,7 @@ open(#{} = Db0, Options) ->
             <<"security_doc">> ->
                 DbAcc#{security_doc => ?JSON_DECODE(Val)}
         end
-    end, Db1, get_config(Db1)).
+    end, Db2, get_config(Db2)).
 
 
 reopen(#{} = OldDb) ->
@@ -600,11 +599,14 @@ init_db(Tx, DbName, Options) ->
     Root = erlfdb_directory:root(),
     CouchDB = erlfdb_directory:create_or_open(Tx, Root, [<<"couchdb">>]),
     Prefix = erlfdb_directory:get_name(CouchDB),
+    Version = erlfdb:wait(erlfdb:get(Tx, ?METADATA_VERSION_KEY)),
     #{
         name => DbName,
         tx => Tx,
         layer_prefix => Prefix,
-        options => Options
+        md_version => Version,
+
+        db_options => Options
     }.
 
 
@@ -728,36 +730,17 @@ ensure_current(#{} = Db) ->
     end.
 
 
-tx_wrap(Tx, Fun) ->
-    case get(erlfdb_error) of
-        ?COMMIT_UNKNOWN_RESULT ->
-            tx_check_applied(Tx, Fun);
-        _ ->
-            tx_attempt(Tx, Fun)
-    end.
+is_transaction_applied(Tx) ->
+    is_commit_unknown_result()
+        andalso has_transaction_id()
+        andalso transaction_id_exist(Tx).
 
 
-tx_clear() ->
-    fabric2_txid_cleaner:remove(get(?PDICT_TX_ID_KEY)),
-    put(?PDICT_TX_ID_KEY, undefined),
-    put(?PDICT_TX_RES_KEY, undefined).
+get_previous_transaction_result() ->
+    get(?PDICT_TX_RES_KEY).
 
 
-tx_check_applied(Tx, Fun) ->
-    case get(?PDICT_TX_ID_KEY) of
-        undefined ->
-            tx_attempt(Tx, Fun);
-        TxId when is_binary(TxId) ->
-            case erlfdb:wait(erlfdb:get(Tx, TxId)) of
-                <<>> ->
-                    get(?PDICT_TX_RES_KEY);
-                not_found ->
-                    tx_attempt(Tx, Fun)
-            end
-    end.
-
-
-tx_attempt(Tx, Fun) ->
+execute_transaction(Tx, Fun) ->
     Result = Fun(Tx),
     case erlfdb:is_read_only(Tx) of
         true ->
@@ -770,10 +753,19 @@ tx_attempt(Tx, Fun) ->
     Result.
 
 
-tx_id(Tx) ->
-    Root = erlfdb_directory:root(),
-    CouchDB = erlfdb_directory:create_or_open(Tx, Root, [<<"couchdb">>]),
-    Prefix = erlfdb_directory:get_name(CouchDB),
-    {Mega, Secs, Micro} = os:timestamp(),
-    Key = {?TX_IDS, Mega, Secs, Micro, fabric2_util:uuid()},
-    erlfdb_tuple:pack(Key, Prefix).
+clear_transaction() ->
+    fabric2_txids:remove(get(?PDICT_TX_ID_KEY)),
+    put(?PDICT_TX_ID_KEY, undefined),
+    put(?PDICT_TX_RES_KEY, undefined).
+
+
+is_commit_unknown_result() ->
+    erlfdb:get_last_error() == ?COMMIT_UNKNOWN_RESULT.
+
+
+has_transaction_id() ->
+    is_binary(get(?PDICT_TX_ID_KEY)).
+
+
+transaction_id_exists(Tx) ->
+    erlfdb:wait(erlfdb:get(Tx, get(?PDICT_TX_ID_KEY))) == <<>>.
diff --git a/src/fabric/src/fabric2_sup.erl b/src/fabric/src/fabric2_sup.erl
index 979f847..73c6c1f 100644
--- a/src/fabric/src/fabric2_sup.erl
+++ b/src/fabric/src/fabric2_sup.erl
@@ -40,8 +40,8 @@ init([]) ->
             start => {fabric2_server, start_link, []}
         },
         #{
-            id => fabric2_txid_cleaner,
-            start => {fabric2_txid_cleaner, start_link, []}
+            id => fabric2_txids,
+            start => {fabric2_txids, start_link, []}
         }
     ],
     {ok, {Flags, Children}}.
diff --git a/src/fabric/src/fabric2_txid_cleaner.erl b/src/fabric/src/fabric2_txids.erl
similarity index 89%
rename from src/fabric/src/fabric2_txid_cleaner.erl
rename to src/fabric/src/fabric2_txids.erl
index eaefbcc..b61c754 100644
--- a/src/fabric/src/fabric2_txid_cleaner.erl
+++ b/src/fabric/src/fabric2_txids.erl
@@ -10,13 +10,14 @@
 % License for the specific language governing permissions and limitations under
 % the License.
 
--module(fabric2_txid_cleaner).
+-module(fabric2_txids).
 -behaviour(gen_server).
 -vsn(1).
 
 
 -export([
     start_link/0,
+    create/1,
     remove/1
 ]).
 
@@ -42,6 +43,15 @@ start_link() ->
     gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
 
 
+create(Tx) ->
+    Root = erlfdb_directory:root(),
+    CouchDB = erlfdb_directory:create_or_open(Tx, Root, [<<"couchdb">>]),
+    Prefix = erlfdb_directory:get_name(CouchDB),
+    {Mega, Secs, Micro} = os:timestamp(),
+    Key = {?TX_IDS, Mega, Secs, Micro, fabric2_util:uuid()},
+    erlfdb_tuple:pack(Key, Prefix).
+
+
 remove(TxId) when is_binary(TxId) ->
     gen_server:cast(?MODULE, {remove, TxId});