[couchdb] branch main updated (5f43148 -> ec4b213)

2021-02-26 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a change to branch main
in repository https://gitbox.apache.org/repos/asf/couchdb.git.


from 5f43148  Merge pull request #3365 from 
apache/active-tasks-process-status-main
 add 79b64ea  Fix typo
 add 73875b5  Add failing cases for ebtree:lookup_multi/3 bug
 add ec4b213  Fix ebtree:lookup_multi/3

No new revisions were added by this update.

Summary of changes:
 src/couch_views/test/couch_views_indexer_test.erl | 42 ++-
 src/ebtree/src/ebtree.erl | 14 
 2 files changed, 41 insertions(+), 15 deletions(-)



[couchdb] branch fix-view-row-bug updated (2a66a03 -> f8507e7)

2021-02-26 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a change to branch fix-view-row-bug
in repository https://gitbox.apache.org/repos/asf/couchdb.git.


 discard 2a66a03  Fix ebtree:lookup_multi/3
 discard dc7382f  Add failing cases for ebtree:lookup_multi/3 bug
 add 5a97edc  Add failing cases for ebtree:lookup_multi/3 bug
 add f8507e7  Fix ebtree:lookup_multi/3

This update added new revisions after undoing existing revisions.
That is to say, some revisions that were in the old version of the
branch are not in the new version.  This situation occurs
when a user --force pushes a change and generates a repository
containing something like this:

 * -- * -- B -- O -- O -- O   (2a66a03)
\
 N -- N -- N   refs/heads/fix-view-row-bug (f8507e7)

You should already have received notification emails for all of the O
revisions, and so the following emails describe only the N revisions
from the common base, B.

Any revisions marked "omit" are not gone; other references still
refer to them.  Any revisions marked "discard" are gone forever.

No new revisions were added by this update.

Summary of changes:
 src/couch_views/test/couch_views_indexer_test.erl | 1 -
 1 file changed, 1 deletion(-)



[couchdb] 02/03: Add failing cases for ebtree:lookup_multi/3 bug

2021-02-26 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a commit to branch fix-view-row-bug
in repository https://gitbox.apache.org/repos/asf/couchdb.git

commit dc7382fa11a64fc4b63d19cc4ba95d313340d8a7
Author: Paul J. Davis 
AuthorDate: Fri Feb 26 13:08:42 2021 -0600

Add failing cases for ebtree:lookup_multi/3 bug

These two test cases expose the subtle bug in ebtree:lookup_multi/3
where a key that doesn't exist in the tree can prevent a subsequent
lookup key from matching in the same KV node.
---
 src/couch_views/test/couch_views_indexer_test.erl | 27 +++
 src/ebtree/src/ebtree.erl |  3 ++-
 2 files changed, 29 insertions(+), 1 deletion(-)

diff --git a/src/couch_views/test/couch_views_indexer_test.erl 
b/src/couch_views/test/couch_views_indexer_test.erl
index e18c007..09493db 100644
--- a/src/couch_views/test/couch_views_indexer_test.erl
+++ b/src/couch_views/test/couch_views_indexer_test.erl
@@ -47,6 +47,7 @@ indexer_test_() ->
 ?TDEF_FE(multiple_identical_keys_from_same_doc),
 ?TDEF_FE(fewer_multiple_identical_keys_from_same_doc),
 ?TDEF_FE(multiple_design_docs),
+?TDEF_FE(multiple_doc_update_with_existing_rows),
 ?TDEF_FE(handle_size_key_limits),
 ?TDEF_FE(handle_size_value_limits),
 ?TDEF_FE(index_autoupdater_callback),
@@ -424,6 +425,32 @@ multiple_design_docs(Db) ->
 ?assertError({ddoc_deleted, _}, run_query(Db, DDoc2, ?MAP_FUN1)).
 
 
+multiple_doc_update_with_existing_rows(Db) ->
+couch_log:error("START TEST", []),
+DDoc = create_ddoc(),
+Doc0 = doc(0),
+Doc1 = doc(1),
+
+{ok, _} = fabric2_db:update_doc(Db, DDoc, []),
+{ok, {Pos, Rev}} = fabric2_db:update_doc(Db, Doc1, []),
+
+{ok, Out1} = run_query(Db, DDoc, ?MAP_FUN1),
+
+?assertEqual([row(<<"1">>, 1, 1)], Out1),
+
+Doc2 = Doc1#doc{
+revs = {Pos, [Rev]},
+body = {[{<<"val">>, 2}]}
+},
+{ok, _} = fabric2_db:update_docs(Db, [Doc0, Doc2], []),
+
+{ok, Out2} = run_query(Db, DDoc, ?MAP_FUN1),
+
+?assertEqual([
+row(<<"0">>, 0, 0),
+row(<<"1">>, 2, 2)
+], Out2).
+
 handle_db_recreated_when_running(Db) ->
 DbName = fabric2_db:name(Db),
 
diff --git a/src/ebtree/src/ebtree.erl b/src/ebtree/src/ebtree.erl
index 1a65c9a..bbb0ca8 100644
--- a/src/ebtree/src/ebtree.erl
+++ b/src/ebtree/src/ebtree.erl
@@ -1394,7 +1394,8 @@ lookup_multi_test() ->
 validate_tree(Db, Tree),
 ?assertEqual([{1, 2}], lookup_multi(Db, Tree, [1])),
 ?assertEqual([{15, 16}, {2, 3}], lookup_multi(Db, Tree, [2, 15])),
-?assertEqual([{15, 16}, {4, 5}, {2, 3}], lookup_multi(Db, Tree, [2, 101, 
15, 4, -3])).
+?assertEqual([{15, 16}, {4, 5}, {2, 3}], lookup_multi(Db, Tree, [2, 101, 
15, 4, -3])),
+?assertEqual([{2, 3}], lookup_multi(Db, Tree, [1.5, 2])).
 
 
 insert_multi_test() ->



[couchdb] branch fix-view-row-bug created (now 2a66a03)

2021-02-26 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a change to branch fix-view-row-bug
in repository https://gitbox.apache.org/repos/asf/couchdb.git.


  at 2a66a03  Fix ebtree:lookup_multi/3

This branch includes the following new commits:

 new c9440e6  Fix typo
 new dc7382f  Add failing cases for ebtree:lookup_multi/3 bug
 new 2a66a03  Fix ebtree:lookup_multi/3

The 3 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.




[couchdb] 03/03: Fix ebtree:lookup_multi/3

2021-02-26 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a commit to branch fix-view-row-bug
in repository https://gitbox.apache.org/repos/asf/couchdb.git

commit 2a66a03eb55f88286f3a3c513271daeb34946b30
Author: Paul J. Davis 
AuthorDate: Fri Feb 26 12:37:04 2021 -0600

Fix ebtree:lookup_multi/3

If one of the provided lookup keys doesn't exist in the ebtree, it can
inadvertently prevent a second lookup key from being found if it the
first key greater than the missing lookup key is equal to the second
lookup key.
---
 src/ebtree/src/ebtree.erl | 11 +--
 1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/src/ebtree/src/ebtree.erl b/src/ebtree/src/ebtree.erl
index bbb0ca8..8c921d1 100644
--- a/src/ebtree/src/ebtree.erl
+++ b/src/ebtree/src/ebtree.erl
@@ -173,18 +173,17 @@ lookup_multi_fold(_, {_, [], _} = Acc) ->
 {stop, Acc};
 
 lookup_multi_fold({visit, Key1, Value}, {Tree, [Key2 | Rest], Acc}) ->
-{NewKeys, NewAcc} = case collate(Tree, Key1, Key2) of
+case collate(Tree, Key1, Key2) of
 lt ->
 % Still looking for the next user key
-{[Key2 | Rest], Acc};
+{ok, {Tree, [Key2 | Rest], Acc}};
 eq ->
 % Found a requested key
-{Rest, [{Key2, Value} | Acc]};
+{ok, {Tree, Rest, [{Key2, Value} | Acc]}};
 gt ->
 % The user key wasn't found so we drop it
-{Rest, Acc}
-end,
-{ok, {Tree, NewKeys, NewAcc}};
+lookup_multi_fold({visit, Key1, Value}, {Tree, Rest, Acc})
+end;
 
 lookup_multi_fold({traverse, FKey, LKey, R}, {Tree, [UKey | Rest], Acc}) ->
 case collate(Tree, FKey, UKey, [gt]) of



[couchdb] 01/03: Fix typo

2021-02-26 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a commit to branch fix-view-row-bug
in repository https://gitbox.apache.org/repos/asf/couchdb.git

commit c9440e67ab57c8d3e583af46f143394d3221936e
Author: Paul J. Davis 
AuthorDate: Fri Feb 26 12:45:19 2021 -0600

Fix typo
---
 src/couch_views/test/couch_views_indexer_test.erl | 16 
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/src/couch_views/test/couch_views_indexer_test.erl 
b/src/couch_views/test/couch_views_indexer_test.erl
index a0890da..e18c007 100644
--- a/src/couch_views/test/couch_views_indexer_test.erl
+++ b/src/couch_views/test/couch_views_indexer_test.erl
@@ -42,10 +42,10 @@ indexer_test_() ->
 ?TDEF_FE(updated_docs_without_changes_are_reindexed),
 ?TDEF_FE(deleted_docs_not_indexed),
 ?TDEF_FE(deleted_docs_are_unindexed),
-?TDEF_FE(multipe_docs_with_same_key),
-?TDEF_FE(multipe_keys_from_same_doc),
-?TDEF_FE(multipe_identical_keys_from_same_doc),
-?TDEF_FE(fewer_multipe_identical_keys_from_same_doc),
+?TDEF_FE(multiple_docs_with_same_key),
+?TDEF_FE(multiple_keys_from_same_doc),
+?TDEF_FE(multiple_identical_keys_from_same_doc),
+?TDEF_FE(fewer_multiple_identical_keys_from_same_doc),
 ?TDEF_FE(multiple_design_docs),
 ?TDEF_FE(handle_size_key_limits),
 ?TDEF_FE(handle_size_value_limits),
@@ -216,7 +216,7 @@ deleted_docs_are_unindexed(Db) ->
 end).
 
 
-multipe_docs_with_same_key(Db) ->
+multiple_docs_with_same_key(Db) ->
 DDoc = create_ddoc(),
 Doc1 = doc(0, 1),
 Doc2 = doc(1, 1),
@@ -232,7 +232,7 @@ multipe_docs_with_same_key(Db) ->
 ], Out).
 
 
-multipe_keys_from_same_doc(Db) ->
+multiple_keys_from_same_doc(Db) ->
 DDoc = create_ddoc(multi_emit_different),
 Doc = doc(0, 1),
 
@@ -247,7 +247,7 @@ multipe_keys_from_same_doc(Db) ->
 ], Out).
 
 
-multipe_identical_keys_from_same_doc(Db) ->
+multiple_identical_keys_from_same_doc(Db) ->
 DDoc = create_ddoc(multi_emit_same),
 Doc = doc(0, 1),
 
@@ -262,7 +262,7 @@ multipe_identical_keys_from_same_doc(Db) ->
 ], Out).
 
 
-fewer_multipe_identical_keys_from_same_doc(Db) ->
+fewer_multiple_identical_keys_from_same_doc(Db) ->
 DDoc = create_ddoc(multi_emit_same),
 Doc0 = #doc{
 id = <<"0">>,



[couchdb] branch 3.x-devnode-boot-script updated (e123adf -> 4638b49)

2021-01-21 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a change to branch 3.x-devnode-boot-script
in repository https://gitbox.apache.org/repos/asf/couchdb.git.


from e123adf  Rename boot_node to monitor_parent
 add 4638b49  Add formatting suggestions from python-black

No new revisions were added by this update.

Summary of changes:
 dev/run | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)



[couchdb-erlfdb] tag v1.2.4 created (now efef20c)

2020-12-14 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a change to tag v1.2.4
in repository https://gitbox.apache.org/repos/asf/couchdb-erlfdb.git.


  at efef20c  (commit)
No new revisions were added by this update.



[couchdb-erlfdb] branch main updated: Avoid sending future ready messages when flushed

2020-12-14 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/couchdb-erlfdb.git


The following commit(s) were added to refs/heads/main by this push:
 new efef20c  Avoid sending future ready messages when flushed
efef20c is described below

commit efef20c439daa6c24227e840482f82945e5c2437
Author: Paul J. Davis 
AuthorDate: Mon Dec 14 15:21:22 2020 -0600

Avoid sending future ready messages when flushed

There's a small race condition in `erlfdb:flush_future_message` if the
`is_ready` returns true before the future's callback is invoked to send
the ready message. This adds an API to silence the message from a future
to close this race condition.

Fixes apache/couchdb#3294
---
 c_src/main.c   | 39 +++
 c_src/resources.h  |  1 +
 src/erlfdb.erl |  1 +
 src/erlfdb_nif.erl |  7 +++
 4 files changed, 48 insertions(+)

diff --git a/c_src/main.c b/c_src/main.c
index b1db949..4f669f5 100644
--- a/c_src/main.c
+++ b/c_src/main.c
@@ -84,11 +84,15 @@ erlfdb_future_cb(FDBFuture* fdb_future, void* data)
 caller = future->pid_env;
 }
 
+enif_mutex_lock(future->lock);
+
 if(!future->cancelled) {
 msg = T2(future->msg_env, future->msg_ref, ATOM_ready);
 enif_send(caller, &(future->pid), future->msg_env, msg);
 }
 
+enif_mutex_unlock(future->lock);
+
 // We're now done with this future which means we need
 // to release our handle to it. See erlfdb_create_future
 // for more on why this happens here.
@@ -114,6 +118,7 @@ erlfdb_create_future(ErlNifEnv* env, FDBFuture* future, 
ErlFDBFutureType ftype)
 f->pid_env = env;
 f->msg_env = enif_alloc_env();
 f->msg_ref = enif_make_copy(f->msg_env, ref);
+f->lock = enif_mutex_create("fdb:future_lock");
 f->cancelled = false;
 
 // This resource reference counting dance is a bit
@@ -579,14 +584,47 @@ erlfdb_future_cancel(ErlNifEnv* env, int argc, const 
ERL_NIF_TERM argv[])
 }
 future = (ErlFDBFuture*) res;
 
+enif_mutex_lock(future->lock);
+
 future->cancelled = true;
 fdb_future_cancel(future->future);
 
+enif_mutex_unlock(future->lock);
+
 return ATOM_ok;
 }
 
 
 static ERL_NIF_TERM
+erlfdb_future_silence(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{
+ErlFDBSt* st = (ErlFDBSt*) enif_priv_data(env);
+ErlFDBFuture* future;
+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], ErlFDBFutureRes, )) {
+return enif_make_badarg(env);
+}
+future = (ErlFDBFuture*) res;
+
+enif_mutex_lock(future->lock);
+
+future->cancelled = true;
+
+enif_mutex_unlock(future->lock);
+
+return ATOM_ok;
+}
+
+static ERL_NIF_TERM
 erlfdb_future_is_ready(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
 {
 ErlFDBSt* st = (ErlFDBSt*) enif_priv_data(env);
@@ -2158,6 +2196,7 @@ static ErlNifFunc funcs[] =
 NIF_FUNC(erlfdb_setup_network, 0),
 
 NIF_FUNC(erlfdb_future_cancel, 1),
+NIF_FUNC(erlfdb_future_silence, 1),
 NIF_FUNC(erlfdb_future_is_ready, 1),
 NIF_FUNC(erlfdb_future_get_error, 1),
 NIF_FUNC(erlfdb_future_get, 1),
diff --git a/c_src/resources.h b/c_src/resources.h
index 6694a99..b25a43f 100644
--- a/c_src/resources.h
+++ b/c_src/resources.h
@@ -44,6 +44,7 @@ typedef struct _ErlFDBFuture
 ErlNifEnv* pid_env;
 ErlNifEnv* msg_env;
 ERL_NIF_TERM msg_ref;
+ErlNifMutex* lock;
 bool cancelled;
 } ErlFDBFuture;
 
diff --git a/src/erlfdb.erl b/src/erlfdb.erl
index d2ddb1f..506b4b0 100644
--- a/src/erlfdb.erl
+++ b/src/erlfdb.erl
@@ -789,6 +789,7 @@ options_to_fold_st(StartKey, EndKey, Options) ->
 
 
 flush_future_message(?IS_FUTURE = Future) ->
+erlfdb_nif:future_silence(Future),
 {erlfdb_future, MsgRef, _Res} = Future,
 receive
 {MsgRef, ready} -> ok
diff --git a/src/erlfdb_nif.erl b/src/erlfdb_nif.erl
index 7ec8e52..ddb7d0f 100644
--- a/src/erlfdb_nif.erl
+++ b/src/erlfdb_nif.erl
@@ -21,6 +21,7 @@
 get_max_api_version/0,
 
 future_cancel/1,
+future_silence/1,
 future_is_ready/1,
 future_get_error/1,
 future_get/1,
@@ -195,6 +196,11 @@ future_cancel({erlfdb_future, _Ref, Ft}) ->
 erlfdb_future_cancel(Ft).
 
 
+-spec future_silence(future()) -> ok.
+future_silence({erlfdb_future, _Ref, Ft}) ->
+erlfdb_future_silence(Ft).
+
+
 -spec future_is_ready(future()) -> boolean().
 future_is_ready({erlfdb_future, _Ref, Ft}) ->
 erlfdb_future_is_ready(Ft).
@@ -527,6 +533,7 @@ erlfdb_setup_network() -> ?NOT_LOADED.
 
 % Futures
 erlfdb_future_cancel(_Future) -> ?NOT_LOADED.
+erlfdb_future_silence(_Future) -&g

[couchdb-erlfdb] branch add-silence-future-api created (now 50e2c9b)

2020-12-14 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a change to branch add-silence-future-api
in repository https://gitbox.apache.org/repos/asf/couchdb-erlfdb.git.


  at 50e2c9b  Avoid sending future ready messages when flushed

This branch includes the following new commits:

 new 50e2c9b  Avoid sending future ready messages when flushed

The 1 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.




[couchdb-erlfdb] 01/01: Avoid sending future ready messages when flushed

2020-12-14 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a commit to branch add-silence-future-api
in repository https://gitbox.apache.org/repos/asf/couchdb-erlfdb.git

commit 50e2c9b07e56b669a9068308d2f95c6517aa75a4
Author: Paul J. Davis 
AuthorDate: Mon Dec 14 15:21:22 2020 -0600

Avoid sending future ready messages when flushed

There's a small race condition in `erlfdb:flush_future_message` if the
`is_ready` returns true before the future's callback is invoked to send
the ready message. This adds an API to silence the message from a future
to close this race condition.

Fixes apache/couchdb#3294
---
 c_src/main.c   | 39 +++
 c_src/resources.h  |  1 +
 src/erlfdb.erl |  1 +
 src/erlfdb_nif.erl |  7 +++
 4 files changed, 48 insertions(+)

diff --git a/c_src/main.c b/c_src/main.c
index b1db949..4f669f5 100644
--- a/c_src/main.c
+++ b/c_src/main.c
@@ -84,11 +84,15 @@ erlfdb_future_cb(FDBFuture* fdb_future, void* data)
 caller = future->pid_env;
 }
 
+enif_mutex_lock(future->lock);
+
 if(!future->cancelled) {
 msg = T2(future->msg_env, future->msg_ref, ATOM_ready);
 enif_send(caller, &(future->pid), future->msg_env, msg);
 }
 
+enif_mutex_unlock(future->lock);
+
 // We're now done with this future which means we need
 // to release our handle to it. See erlfdb_create_future
 // for more on why this happens here.
@@ -114,6 +118,7 @@ erlfdb_create_future(ErlNifEnv* env, FDBFuture* future, 
ErlFDBFutureType ftype)
 f->pid_env = env;
 f->msg_env = enif_alloc_env();
 f->msg_ref = enif_make_copy(f->msg_env, ref);
+f->lock = enif_mutex_create("fdb:future_lock");
 f->cancelled = false;
 
 // This resource reference counting dance is a bit
@@ -579,14 +584,47 @@ erlfdb_future_cancel(ErlNifEnv* env, int argc, const 
ERL_NIF_TERM argv[])
 }
 future = (ErlFDBFuture*) res;
 
+enif_mutex_lock(future->lock);
+
 future->cancelled = true;
 fdb_future_cancel(future->future);
 
+enif_mutex_unlock(future->lock);
+
 return ATOM_ok;
 }
 
 
 static ERL_NIF_TERM
+erlfdb_future_silence(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{
+ErlFDBSt* st = (ErlFDBSt*) enif_priv_data(env);
+ErlFDBFuture* future;
+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], ErlFDBFutureRes, )) {
+return enif_make_badarg(env);
+}
+future = (ErlFDBFuture*) res;
+
+enif_mutex_lock(future->lock);
+
+future->cancelled = true;
+
+enif_mutex_unlock(future->lock);
+
+return ATOM_ok;
+}
+
+static ERL_NIF_TERM
 erlfdb_future_is_ready(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
 {
 ErlFDBSt* st = (ErlFDBSt*) enif_priv_data(env);
@@ -2158,6 +2196,7 @@ static ErlNifFunc funcs[] =
 NIF_FUNC(erlfdb_setup_network, 0),
 
 NIF_FUNC(erlfdb_future_cancel, 1),
+NIF_FUNC(erlfdb_future_silence, 1),
 NIF_FUNC(erlfdb_future_is_ready, 1),
 NIF_FUNC(erlfdb_future_get_error, 1),
 NIF_FUNC(erlfdb_future_get, 1),
diff --git a/c_src/resources.h b/c_src/resources.h
index 6694a99..b25a43f 100644
--- a/c_src/resources.h
+++ b/c_src/resources.h
@@ -44,6 +44,7 @@ typedef struct _ErlFDBFuture
 ErlNifEnv* pid_env;
 ErlNifEnv* msg_env;
 ERL_NIF_TERM msg_ref;
+ErlNifMutex* lock;
 bool cancelled;
 } ErlFDBFuture;
 
diff --git a/src/erlfdb.erl b/src/erlfdb.erl
index d2ddb1f..506b4b0 100644
--- a/src/erlfdb.erl
+++ b/src/erlfdb.erl
@@ -789,6 +789,7 @@ options_to_fold_st(StartKey, EndKey, Options) ->
 
 
 flush_future_message(?IS_FUTURE = Future) ->
+erlfdb_nif:future_silence(Future),
 {erlfdb_future, MsgRef, _Res} = Future,
 receive
 {MsgRef, ready} -> ok
diff --git a/src/erlfdb_nif.erl b/src/erlfdb_nif.erl
index 7ec8e52..ddb7d0f 100644
--- a/src/erlfdb_nif.erl
+++ b/src/erlfdb_nif.erl
@@ -21,6 +21,7 @@
 get_max_api_version/0,
 
 future_cancel/1,
+future_silence/1,
 future_is_ready/1,
 future_get_error/1,
 future_get/1,
@@ -195,6 +196,11 @@ future_cancel({erlfdb_future, _Ref, Ft}) ->
 erlfdb_future_cancel(Ft).
 
 
+-spec future_silence(future()) -> ok.
+future_silence({erlfdb_future, _Ref, Ft}) ->
+erlfdb_future_silence(Ft).
+
+
 -spec future_is_ready(future()) -> boolean().
 future_is_ready({erlfdb_future, _Ref, Ft}) ->
 erlfdb_future_is_ready(Ft).
@@ -527,6 +533,7 @@ erlfdb_setup_network() -> ?NOT_LOADED.
 
 % Futures
 erlfdb_future_cancel(_Future) -> ?NOT_LOADED.
+erlfdb_future_silence(_Future) -> ?NOT_LOADED.
 erlfdb_future_is_ready(_Future) -> ?NOT_LOADED.
 erlfdb_future_get_error(_Future) -> ?NOT_LOADED.
 erlfdb_future_get(_Future) -> ?NOT_LOADED.



[couchdb-infra-cm] branch main updated: Ensure root account is locked

2020-12-14 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/couchdb-infra-cm.git


The following commit(s) were added to refs/heads/main by this push:
 new 24bea20  Ensure root account is locked
24bea20 is described below

commit 24bea20e9a098cf4a462a4b5d9dbabbea84f2ec6
Author: Paul J. Davis 
AuthorDate: Mon Dec 14 15:11:50 2020 -0600

Ensure root account is locked

Its locked by default but we might as well add the extra protection just
in case.
---
 roles/common/tasks/main.yml | 5 +
 1 file changed, 5 insertions(+)

diff --git a/roles/common/tasks/main.yml b/roles/common/tasks/main.yml
index 814e1e8..639 100644
--- a/roles/common/tasks/main.yml
+++ b/roles/common/tasks/main.yml
@@ -9,6 +9,11 @@
 - https://github.com/nickva.keys
 - https://github.com/wohali.keys
 
+- name: Lock root account
+  user:
+name: root
+password_lock: true
+
 - name: Disable password authentication
   lineinfile:
 dest: /etc/ssh/sshd_config



[couchdb-infra-cm] branch main updated: Harden SSH settings on CI nodes

2020-12-14 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/couchdb-infra-cm.git


The following commit(s) were added to refs/heads/main by this push:
 new dc63a8c  Harden SSH settings on CI nodes
dc63a8c is described below

commit dc63a8cd29401edb0b79761fcf88ac32fe3797d2
Author: Paul J. Davis 
AuthorDate: Mon Dec 14 14:41:59 2020 -0600

Harden SSH settings on CI nodes
---
 roles/common/handlers/main.yml |  4 
 roles/common/tasks/main.yml| 22 ++
 2 files changed, 26 insertions(+)

diff --git a/roles/common/handlers/main.yml b/roles/common/handlers/main.yml
new file mode 100644
index 000..660b2b7
--- /dev/null
+++ b/roles/common/handlers/main.yml
@@ -0,0 +1,4 @@
+- name: restart sshd
+  service:
+name: sshd
+state: restarted
\ No newline at end of file
diff --git a/roles/common/tasks/main.yml b/roles/common/tasks/main.yml
index a449f36..814e1e8 100644
--- a/roles/common/tasks/main.yml
+++ b/roles/common/tasks/main.yml
@@ -9,6 +9,28 @@
 - https://github.com/nickva.keys
 - https://github.com/wohali.keys
 
+- name: Disable password authentication
+  lineinfile:
+dest: /etc/ssh/sshd_config
+regexp: '^(#\s*)?PasswordAuthentication'
+line: "PasswordAuthentication no"
+state: present
+  notify: restart sshd
+
+- name: Disable empty password login
+  lineinfile:
+dest: /etc/ssh/sshd_config
+regexp: '^(#\s*)?PermitEmptyPasswords'
+line: 'PermitEmptyPasswords no'
+  notify: restart sshd
+
+- name: Disable challenge response authentication
+  lineinfile:
+dest: /etc/ssh/sshd_config
+regexp: '^(#\s*)?ChallengeResponseAuthentication'
+line: 'ChallengeResponseAuthentication no'
+  notify: restart sshd
+
 - name: Install basic ubiquitous packages
   apt:
 name: "{{ packages }}"



[couchdb-erlfdb] branch add-stats created (now 187b585)

2020-12-10 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a change to branch add-stats
in repository https://gitbox.apache.org/repos/asf/couchdb-erlfdb.git.


  at 187b585  Add metrics for tracking futures

This branch includes the following new commits:

 new 187b585  Add metrics for tracking futures

The 1 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.




[couchdb-erlfdb] 01/01: Add metrics for tracking futures

2020-12-10 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a commit to branch add-stats
in repository https://gitbox.apache.org/repos/asf/couchdb-erlfdb.git

commit 187b585b0bc7c2bcc27fd875f3d59e54a9c028ac
Author: Paul J. Davis 
AuthorDate: Thu Dec 10 13:14:22 2020 -0600

Add metrics for tracking futures
---
 c_src/atom_names.h |  6 +
 c_src/main.c   | 38 +++-
 c_src/metrics.cc   | 74 ++
 c_src/metrics.h| 28 +
 c_src/resources.c  |  3 +++
 rebar.config   |  4 +--
 src/erlfdb.erl |  7 +-
 src/erlfdb_nif.erl |  8 +-
 8 files changed, 163 insertions(+), 5 deletions(-)

diff --git a/c_src/atom_names.h b/c_src/atom_names.h
index 98b5c4f..377df1f 100644
--- a/c_src/atom_names.h
+++ b/c_src/atom_names.h
@@ -143,3 +143,9 @@ ATOM_MAP(write);
 ATOM_MAP(retryable);
 ATOM_MAP(maybe_committed);
 ATOM_MAP(retryable_not_committed);
+
+// Metrics
+ATOM_MAP(futures_created);
+ATOM_MAP(futures_destroyed);
+ATOM_MAP(futures_fired);
+ATOM_MAP(futures_read);
\ No newline at end of file
diff --git a/c_src/main.c b/c_src/main.c
index b1db949..e7ac014 100644
--- a/c_src/main.c
+++ b/c_src/main.c
@@ -18,6 +18,7 @@
 #include "fdb.h"
 
 #include "atoms.h"
+#include "metrics.h"
 #include "resources.h"
 #include "util.h"
 
@@ -95,6 +96,8 @@ erlfdb_future_cb(FDBFuture* fdb_future, void* data)
 
 enif_release_resource(future);
 
+erlfdb_future_fired();
+
 return;
 }
 
@@ -159,6 +162,8 @@ erlfdb_create_future(ErlNifEnv* env, FDBFuture* future, 
ErlFDBFutureType ftype)
 // thread has a reference. If its 1 then only
 // Erlang has a reference.
 
+erlfdb_future_created();
+
 return T3(env, ATOM_erlfdb_future, ref, ret);
 }
 
@@ -173,6 +178,8 @@ erlfdb_future_get_void(ErlNifEnv* env, ErlFDBFuture* f)
 return erlfdb_erlang_error(env, err);
 }
 
+erlfdb_future_read();
+
 return ATOM_ok;
 }
 
@@ -191,6 +198,8 @@ erlfdb_future_get_int64(ErlNifEnv* env, ErlFDBFuture* f)
 
 nif_res = fdb_res;
 
+erlfdb_future_read();
+
 return enif_make_int64(env, nif_res);
 }
 
@@ -212,6 +221,8 @@ erlfdb_future_get_key(ErlNifEnv* env, ErlFDBFuture* f)
 buf = enif_make_new_binary(env, len, );
 memcpy(buf, key, len);
 
+erlfdb_future_read();
+
 return ret;
 }
 
@@ -238,6 +249,8 @@ erlfdb_future_get_value(ErlNifEnv* env, ErlFDBFuture* f)
 buf = enif_make_new_binary(env, len, );
 memcpy(buf, val, len);
 
+erlfdb_future_read();
+
 return ret;
 }
 
@@ -266,6 +279,8 @@ erlfdb_future_get_string_array(ErlNifEnv* env, 
ErlFDBFuture* f)
 ret = enif_make_list_cell(env, bin, ret);
 }
 
+erlfdb_future_read();
+
 return ret;
 }
 
@@ -298,6 +313,8 @@ erlfdb_future_get_keyvalue_array(ErlNifEnv* env, 
ErlFDBFuture* f)
 ret = enif_make_list_cell(env, T2(env, key, val), ret);
 }
 
+erlfdb_future_read();
+
 if(more) {
 return T3(env, ret, enif_make_int(env, count), ATOM_true);
 } else {
@@ -2145,6 +2162,23 @@ erlfdb_error_predicate(ErlNifEnv* env, int argc, const 
ERL_NIF_TERM argv[])
 }
 }
 
+static ERL_NIF_TERM
+erlfdb_get_metrics(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{
+ERL_NIF_TERM metrics[4];
+
+ERL_NIF_TERM created = enif_make_uint64(env, erlfdb_num_futures_created());
+ERL_NIF_TERM destroyed = enif_make_uint64(env, 
erlfdb_num_futures_destroyed());
+ERL_NIF_TERM fired = enif_make_uint64(env, erlfdb_num_futures_fired());
+ERL_NIF_TERM read = enif_make_uint64(env, erlfdb_num_futures_read());
+
+metrics[0] = T2(env, ATOM_futures_created, created);
+metrics[1] = T2(env, ATOM_futures_destroyed, destroyed);
+metrics[2] = T2(env, ATOM_futures_fired, fired);
+metrics[3] = T2(env, ATOM_futures_read, read);
+
+return enif_make_list_from_array(env, metrics, 4);
+}
 
 #define NIF_FUNC(name, arity) {#name, arity, name}
 static ErlNifFunc funcs[] =
@@ -2192,7 +2226,9 @@ static ErlNifFunc funcs[] =
 NIF_FUNC(erlfdb_transaction_get_writes_allowed, 1),
 
 NIF_FUNC(erlfdb_get_error, 1),
-NIF_FUNC(erlfdb_error_predicate, 2)
+NIF_FUNC(erlfdb_error_predicate, 2),
+
+NIF_FUNC(erlfdb_get_metrics, 0)
 };
 #undef NIF_FUNC
 
diff --git a/c_src/metrics.cc b/c_src/metrics.cc
new file mode 100644
index 000..35f73b4
--- /dev/null
+++ b/c_src/metrics.cc
@@ -0,0 +1,74 @@
+// 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

[couchdb-infra-cm] branch main updated: Update inventory after rebuilding the farm

2020-12-04 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/couchdb-infra-cm.git


The following commit(s) were added to refs/heads/main by this push:
 new 8ebaeb3  Update inventory after rebuilding the farm
8ebaeb3 is described below

commit 8ebaeb315aa8a68b190099610f5b98705be4de16
Author: Paul J. Davis 
AuthorDate: Fri Dec 4 12:12:59 2020 -0600

Update inventory after rebuilding the farm

IBM needed me to recreate the CI farm because they had block storage
instances that needed updating to a never version.
---
 production | 92 --
 ssh.cfg| 36 ++--
 2 files changed, 38 insertions(+), 90 deletions(-)

diff --git a/production b/production
index 5670102..da6f32d 100644
--- a/production
+++ b/production
@@ -2,17 +2,17 @@ all:
   children:
 bastions:
   hosts:
-couchdb-bastion-x86-64-debian-dal-1-1:
+couchdb-bastion-x86-64-debian-dal-1-01:
   instance:
-created_at: '2020-01-07T18:38:33Z'
-id: 0717_5ecb1169-95ac-465b-a505-d172093972d1
-name: couchdb-bastion-x86-64-debian-dal-1-1
+created_at: '2020-12-04T17:51:31Z'
+id: 0717_27810451-1a4b-4f12-8fcb-47375063cf28
+name: couchdb-bastion-x86-64-debian-dal-1-01
 profile: cx2-2x4
 subnet: couchdb-ci-farm-dal-1
 vpc: couchdb-ci-farm-vpc
 zone: us-south-1
   ip_addrs:
-private: 10.240.0.11
+private: 10.240.0.17
 public: 169.48.153.153
   system:
 arch: amd64
@@ -20,44 +20,10 @@ all:
 ram: 4
 ci_agents:
   hosts:
-couchdb-worker-ppc64le-ubuntu-dal-1-01:
-  instance:
-created_at: '2020-01-10T18:59:17Z'
-id: 0717_00d6f517-25e3-417c-b9d5-0d4fa8cde5ac
-name: couchdb-worker-ppc64le-ubuntu-dal-1-01
-profile: cp2-4x8
-subnet: couchdb-ci-farm-dal-1
-vpc: couchdb-ci-farm-vpc
-zone: us-south-1
-  ip_addrs:
-bastion: 169.48.153.153
-private: 10.240.0.20
-public: null
-  system:
-arch: power
-num_cpus: 4
-ram: 8
-couchdb-worker-ppc64le-ubuntu-dal-1-02:
-  instance:
-created_at: '2020-01-10T19:04:46Z'
-id: 0717_a0c8bd5a-5ffe-44da-8058-b2a87180ce9b
-name: couchdb-worker-ppc64le-ubuntu-dal-1-02
-profile: cp2-4x8
-subnet: couchdb-ci-farm-dal-1
-vpc: couchdb-ci-farm-vpc
-zone: us-south-1
-  ip_addrs:
-bastion: 169.48.153.153
-private: 10.240.0.21
-public: null
-  system:
-arch: power
-num_cpus: 4
-ram: 8
 couchdb-worker-x86-64-debian-dal-1-01:
   instance:
-created_at: '2019-12-11T16:50:33Z'
-id: 0717_4d64226a-ffad-4523-b5b3-78769a1d0bbe
+created_at: '2020-12-04T17:37:42Z'
+id: 0717_0380c8b9-988a-4938-aa9d-95ebf50ff9a7
 name: couchdb-worker-x86-64-debian-dal-1-01
 profile: cx2-4x8
 subnet: couchdb-ci-farm-dal-1
@@ -65,7 +31,7 @@ all:
 zone: us-south-1
   ip_addrs:
 bastion: 169.48.153.153
-private: 10.240.0.4
+private: 10.240.0.16
 public: null
   system:
 arch: amd64
@@ -73,8 +39,8 @@ all:
 ram: 8
 couchdb-worker-x86-64-debian-dal-1-02:
   instance:
-created_at: '2019-12-11T16:51:02Z'
-id: 0717_d97c67df-1f04-41f8-9461-9b1d5721e408
+created_at: '2020-12-04T17:37:20Z'
+id: 0717_20746912-9251-417a-8b2e-75de411c37a4
 name: couchdb-worker-x86-64-debian-dal-1-02
 profile: cx2-4x8
 subnet: couchdb-ci-farm-dal-1
@@ -82,7 +48,7 @@ all:
 zone: us-south-1
   ip_addrs:
 bastion: 169.48.153.153
-private: 10.240.0.5
+private: 10.240.0.15
 public: null
   system:
 arch: amd64
@@ -90,8 +56,8 @@ all:
 ram: 8
 couchdb-worker-x86-64-debian-dal-1-03:
   instance:
-created_at: '2019-12-11T16:51:21Z'
-id: 0717_04df61d7-fb30-4251-9f59-7566c93c8a92
+created_at: '2020-12-04T17:36:58Z'
+id: 0717_c158fd8e-69d9-486d-86a9-094421b5c923
 name: couchdb-worker-x86-64-debian-dal-1-03
 profile: cx2-4x8
 subnet: couchdb-ci-farm-dal-1
@@ -99,7 +65,7 @@ all:
 zone: us-south-1
   ip_addrs:
 bastion: 169.48.153.153
-private: 10.240.0.6
+private: 10.240.0.14
 public: null

[couchdb] 02/04: Allow specifying an end_key for fold_changes

2020-11-17 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/couchdb.git

commit 0e91f2f608d4a920b6c22f1fe1eb9e0ea6982d5a
Author: Paul J. Davis 
AuthorDate: Fri Nov 13 15:13:07 2020 -0600

Allow specifying an end_key for fold_changes

This is useful so that read conflicts on the changes feed will
eventually be resolved. Without an end key specified a reader could end
up in an infinite conflict retry loop if there are clients updating
documents in the database.
---
 src/fabric/src/fabric2_db.erl  | 18 +++---
 src/fabric/test/fabric2_changes_fold_tests.erl | 11 +++
 2 files changed, 22 insertions(+), 7 deletions(-)

diff --git a/src/fabric/src/fabric2_db.erl b/src/fabric/src/fabric2_db.erl
index b3e510b..a310470 100644
--- a/src/fabric/src/fabric2_db.erl
+++ b/src/fabric/src/fabric2_db.erl
@@ -1093,14 +1093,18 @@ fold_changes(Db, SinceSeq, UserFun, UserAcc, Options) ->
 end,
 
 StartKey = get_since_seq(TxDb, Dir, SinceSeq),
-EndKey = case Dir of
-rev -> fabric2_util:seq_zero_vs();
-_ -> fabric2_util:seq_max_vs()
+EndKey = case fabric2_util:get_value(end_key, Options) of
+undefined when Dir == rev ->
+fabric2_util:seq_zero_vs();
+undefined ->
+fabric2_util:seq_max_vs();
+EK when is_binary(EK) ->
+fabric2_fdb:seq_to_vs(EK);
+EK when is_tuple(EK), element(1, EK) == versionstamp ->
+EK
 end,
-FoldOpts = [
-{start_key, StartKey},
-{end_key, EndKey}
-] ++ RestartTx ++ Options,
+BaseOpts = [{start_key, StartKey}] ++ RestartTx ++ Options,
+FoldOpts = lists:keystore(end_key, 1, BaseOpts, {end_key, EndKey}),
 
 {ok, fabric2_fdb:fold_range(TxDb, Prefix, fun({K, V}, Acc) ->
 {SeqVS} = erlfdb_tuple:unpack(K, Prefix),
diff --git a/src/fabric/test/fabric2_changes_fold_tests.erl 
b/src/fabric/test/fabric2_changes_fold_tests.erl
index 8541d97..fa79f25 100644
--- a/src/fabric/test/fabric2_changes_fold_tests.erl
+++ b/src/fabric/test/fabric2_changes_fold_tests.erl
@@ -40,6 +40,7 @@ changes_fold_test_() ->
 ?TDEF_FE(fold_changes_basic_rev),
 ?TDEF_FE(fold_changes_since_now_rev),
 ?TDEF_FE(fold_changes_since_seq_rev),
+?TDEF_FE(fold_changes_with_end_key),
 ?TDEF_FE(fold_changes_basic_tx_too_old),
 ?TDEF_FE(fold_changes_reverse_tx_too_old),
 ?TDEF_FE(fold_changes_tx_too_old_with_single_row_emits),
@@ -124,6 +125,16 @@ fold_changes_since_seq_rev({Db, DocRows}) ->
 fold_changes_since_seq_rev({Db, RestRows}).
 
 
+fold_changes_with_end_key({Db, DocRows}) ->
+lists:foldl(fun(DocRow, Acc) ->
+EndSeq = maps:get(sequence, DocRow),
+Changes = changes(Db, 0, [{end_key, EndSeq}]),
+NewAcc = [DocRow | Acc],
+?assertEqual(Changes, NewAcc),
+NewAcc
+end, [], DocRows).
+
+
 fold_changes_basic_tx_too_old({Db, DocRows0}) ->
 DocRows = lists:reverse(DocRows0),
 



[couchdb] 03/04: Minimize conflicts while building views

2020-11-17 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/couchdb.git

commit 27e8e332cf974bff69b86a8d3c5e2f5a6de4125f
Author: Paul J. Davis 
AuthorDate: Fri Nov 13 14:11:00 2020 -0600

Minimize conflicts while building views

This flips the view indexer to grab the database update_seq outside of
the update transaction. Previously we would cosntantly refresh the
db_seq value on every retry of the transactional loop.

We use a snapshot to get the update_seq so that we don't trigger
spurious read conflicts with any clients that might be updating the
database.
---
 src/couch_views/src/couch_views_indexer.erl   | 54 +++
 src/couch_views/test/couch_views_indexer_test.erl | 45 +++
 2 files changed, 91 insertions(+), 8 deletions(-)

diff --git a/src/couch_views/src/couch_views_indexer.erl 
b/src/couch_views/src/couch_views_indexer.erl
index 2735f66..83ccb2c 100644
--- a/src/couch_views/src/couch_views_indexer.erl
+++ b/src/couch_views/src/couch_views_indexer.erl
@@ -86,15 +86,22 @@ init() ->
 fail_job(Job, Data, sig_changed, "Design document was modified")
 end,
 
+DbSeq = fabric2_fdb:transactional(Db, fun(TxDb) ->
+fabric2_fdb:with_snapshot(TxDb, fun(SSDb) ->
+fabric2_db:get_update_seq(SSDb)
+end)
+end),
+
 State = #{
 tx_db => undefined,
 db_uuid => DbUUID,
-db_seq => undefined,
+db_seq => DbSeq,
 view_seq => undefined,
 last_seq => undefined,
 view_vs => undefined,
 job => Job,
 job_data => Data,
+rows_processed => 0,
 count => 0,
 changes_done => 0,
 doc_acc => [],
@@ -206,8 +213,6 @@ do_update(Db, Mrst0, State0) ->
 {ok, State2} = fold_changes(State1),
 
 #{
-count := Count,
-limit := Limit,
 doc_acc := DocAcc,
 last_seq := LastSeq,
 view_vs := ViewVS,
@@ -228,7 +233,7 @@ do_update(Db, Mrst0, State0) ->
 total_kvs => TotalKVs
 },
 
-case Count < Limit of
+case is_update_finished(State2) of
 true ->
 maybe_set_build_status(TxDb, Mrst2, ViewVS,
 ?INDEX_READY),
@@ -249,6 +254,20 @@ do_update(Db, Mrst0, State0) ->
 end).
 
 
+is_update_finished(State) ->
+#{
+db_seq := DbSeq,
+last_seq := LastSeq,
+view_vs := ViewVs
+} = State,
+AtDbSeq = LastSeq == DbSeq,
+AtViewVs = case ViewVs of
+not_found -> false;
+_ -> LastSeq == fabric2_fdb:vs_to_seq(ViewVs)
+end,
+AtDbSeq orelse AtViewVs.
+
+
 maybe_set_build_status(_TxDb, _Mrst1, not_found, _State) ->
 ok;
 
@@ -258,7 +277,7 @@ maybe_set_build_status(TxDb, Mrst1, _ViewVS, State) ->
 
 % In the first iteration of update we need
 % to populate our db and view sequences
-get_update_start_state(TxDb, Mrst, #{db_seq := undefined} = State) ->
+get_update_start_state(TxDb, Mrst, #{view_seq := undefined} = State) ->
 #{
 view_vs := ViewVS,
 view_seq := ViewSeq
@@ -266,7 +285,6 @@ get_update_start_state(TxDb, Mrst, #{db_seq := undefined} = 
State) ->
 
 State#{
 tx_db := TxDb,
-db_seq := fabric2_db:get_update_seq(TxDb),
 view_vs := ViewVS,
 view_seq := ViewSeq,
 last_seq := ViewSeq
@@ -281,18 +299,36 @@ get_update_start_state(TxDb, _Idx, State) ->
 fold_changes(State) ->
 #{
 view_seq := SinceSeq,
+db_seq := DbSeq,
 limit := Limit,
 tx_db := TxDb
 } = State,
 
+FoldState = State#{
+rows_processed := 0
+},
+
 Fun = fun process_changes/2,
-Opts = [{limit, Limit}, {restart_tx, false}],
-fabric2_db:fold_changes(TxDb, SinceSeq, Fun, State, Opts).
+Opts = [
+{end_key, fabric2_fdb:seq_to_vs(DbSeq)},
+{limit, Limit},
+{restart_tx, false}
+],
+case fabric2_db:fold_changes(TxDb, SinceSeq, Fun, FoldState, Opts) of
+{ok, #{rows_processed := 0} = FinalState} when Limit > 0 ->
+% If we read zero rows with a non-zero limit
+% it means we've caught up to the DbSeq as our
+% last_seq.
+{ok, FinalState#{last_seq := DbSeq}};
+Result ->
+Result
+end.
 
 
 process_changes(Change, Acc) ->
 #{
 doc_acc := DocAcc,
+rows_processed := RowsProcessed,
 count := Count,
 design_opts := DesignOpts,
 view_vs := ViewVS
@@ -308,12 +344,14 @@ process_changes(Change, Acc) ->
 Acc1 = case {Id, IncludeDesign} of
 {<>, false} ->
 maps:merge(Acc, #{
+rows_processed => RowsProcessed + 1,
   

[couchdb] 01/04: Allow snapshots through fabric2_fdb:transactional

2020-11-17 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/couchdb.git

commit 1b30d0810ac0d985676c90dc1b6532f9fb84284c
Author: Paul J. Davis 
AuthorDate: Fri Nov 13 14:08:52 2020 -0600

Allow snapshots through fabric2_fdb:transactional
---
 src/fabric/src/fabric2_fdb.erl |  17 
 src/fabric/test/fabric2_snapshot_tests.erl | 134 +
 2 files changed, 151 insertions(+)

diff --git a/src/fabric/src/fabric2_fdb.erl b/src/fabric/src/fabric2_fdb.erl
index aa2bade..1690f2f 100644
--- a/src/fabric/src/fabric2_fdb.erl
+++ b/src/fabric/src/fabric2_fdb.erl
@@ -18,6 +18,8 @@
 transactional/3,
 transactional/2,
 
+with_snapshot/2,
+
 create/2,
 open/2,
 ensure_current/1,
@@ -150,6 +152,11 @@ transactional(#{tx := undefined} = Db, Fun) ->
 transactional(Db#{reopen => true}, Fun)
 end)
 end;
+transactional(#{tx := {erlfdb_snapshot, _}} = Db, Fun) ->
+DbName = maps:get(name, Db, undefined),
+with_span(Fun, #{'db.name' => DbName}, fun() ->
+Fun(Db)
+end);
 
 transactional(#{tx := {erlfdb_transaction, _}} = Db, Fun) ->
 DbName = maps:get(name, Db, undefined),
@@ -183,6 +190,14 @@ do_transaction(Fun, LayerPrefix) when is_function(Fun, 1) 
->
 end.
 
 
+with_snapshot(#{tx := {erlfdb_transaction, _} = Tx} = TxDb, Fun) ->
+SSDb = TxDb#{tx := erlfdb:snapshot(Tx)},
+Fun(SSDb);
+
+with_snapshot(#{tx := {erlfdb_snapshot, _}} = SSDb, Fun) ->
+Fun(SSDb).
+
+
 create(#{} = Db0, Options) ->
 #{
 name := DbName,
@@ -1865,6 +1880,8 @@ get_db_handle() ->
 end.
 
 
+require_transaction(#{tx := {erlfdb_snapshot, _}} = _Db) ->
+ok;
 require_transaction(#{tx := {erlfdb_transaction, _}} = _Db) ->
 ok;
 require_transaction(#{} = _Db) ->
diff --git a/src/fabric/test/fabric2_snapshot_tests.erl 
b/src/fabric/test/fabric2_snapshot_tests.erl
new file mode 100644
index 000..37ba626
--- /dev/null
+++ b/src/fabric/test/fabric2_snapshot_tests.erl
@@ -0,0 +1,134 @@
+% 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_snapshot_tests).
+
+
+-include_lib("couch/include/couch_db.hrl").
+-include_lib("couch/include/couch_eunit.hrl").
+-include_lib("eunit/include/eunit.hrl").
+-include("fabric2.hrl").
+-include("fabric2_test.hrl").
+
+
+fdb_ss_test_() ->
+{
+"Test snapshot usage",
+setup,
+fun setup/0,
+fun cleanup/1,
+with([
+?TDEF(retry_without_snapshot),
+?TDEF(no_retry_with_snapshot)
+])
+}.
+
+
+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).
+
+
+retry_without_snapshot({Db, _}) ->
+DbName = fabric2_db:name(Db),
+put(retry_count, 0),
+erase(conflict_pid),
+InitDbSeq = fabric2_db:get_update_seq(Db),
+DbSeq = fabric2_fdb:transactional(Db, fun(TxDb) ->
+put(retry_count, get(retry_count) + 1),
+
+% Fetch the update_seq
+Seq = fabric2_db:get_update_seq(TxDb),
+
+% Generate a no-op write so that we don't hit the
+% optimization to skip commits on read-only
+% transactions
+bump_view_size(TxDb),
+
+% Generate a conflicting transaction while
+% we're not yet committed
+case get(conflict_pid) of
+undefined ->
+{Pid, Ref} = spawn_monitor(fun() -> generate_conflict(DbName) 
end),
+receive {'DOWN', Ref, _, _, normal} -> ok end,
+put(conflict_pid, Pid);
+Pid when is_pid(Pid) ->
+ok
+end,
+
+Seq
+end),
+
+?assertEqual(2, get(retry_count)),
+?assertNotEqual(InitDbSeq, DbSeq).
+
+
+no_retry_with_snapshot({Db, _}) ->
+DbName = fabric2_db:name(Db),
+put(retry_count, 0),
+erase(conflict_pid),
+InitDbSeq = fabric2_db:get_update_seq(Db),
+DbSeq = fabric2_fdb:transactional(Db, fun(TxDb) ->
+put(retry_count, get(retry_count) + 1),
+
+% Fetch the update_seq
+Seq = fabric2_fdb:with_snapshot(TxDb, fun(SSDb) ->
+ 

[couchdb] branch main updated (0b98b3b -> 3168a4d)

2020-11-17 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a change to branch main
in repository https://gitbox.apache.org/repos/asf/couchdb.git.


from 0b98b3b  Merge pull request #3274 from cloudant/fix-mango-tests
 new 1b30d08  Allow snapshots through fabric2_fdb:transactional
 new 0e91f2f  Allow specifying an end_key for fold_changes
 new 27e8e33  Minimize conflicts while building views
 new 3168a4d  Remove unnecessary line wraps

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/couch_views/src/couch_views_indexer.erl   |  60 --
 src/couch_views/test/couch_views_indexer_test.erl |  45 
 src/fabric/src/fabric2_db.erl |  18 +--
 src/fabric/src/fabric2_fdb.erl|  17 +++
 src/fabric/test/fabric2_changes_fold_tests.erl|  11 ++
 src/fabric/test/fabric2_snapshot_tests.erl| 134 ++
 6 files changed, 266 insertions(+), 19 deletions(-)
 create mode 100644 src/fabric/test/fabric2_snapshot_tests.erl



[couchdb] 04/04: Remove unnecessary line wraps

2020-11-17 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/couchdb.git

commit 3168a4dbcef7181b67a989e1d723dc6a93e76280
Author: Paul J. Davis 
AuthorDate: Tue Nov 17 11:23:36 2020 -0600

Remove unnecessary line wraps
---
 src/couch_views/src/couch_views_indexer.erl | 6 ++
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/src/couch_views/src/couch_views_indexer.erl 
b/src/couch_views/src/couch_views_indexer.erl
index 83ccb2c..e3b2ad5 100644
--- a/src/couch_views/src/couch_views_indexer.erl
+++ b/src/couch_views/src/couch_views_indexer.erl
@@ -235,10 +235,8 @@ do_update(Db, Mrst0, State0) ->
 
 case is_update_finished(State2) of
 true ->
-maybe_set_build_status(TxDb, Mrst2, ViewVS,
-?INDEX_READY),
-report_progress(State2#{changes_done := ChangesDone},
-finished),
+maybe_set_build_status(TxDb, Mrst2, ViewVS, ?INDEX_READY),
+report_progress(State2#{changes_done := ChangesDone}, 
finished),
 {Mrst2, finished};
 false ->
 State3 = report_progress(State2, update),



[couchdb] 02/04: Allow specifying an end_key for fold_changes

2020-11-17 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/couchdb.git

commit 0e91f2f608d4a920b6c22f1fe1eb9e0ea6982d5a
Author: Paul J. Davis 
AuthorDate: Fri Nov 13 15:13:07 2020 -0600

Allow specifying an end_key for fold_changes

This is useful so that read conflicts on the changes feed will
eventually be resolved. Without an end key specified a reader could end
up in an infinite conflict retry loop if there are clients updating
documents in the database.
---
 src/fabric/src/fabric2_db.erl  | 18 +++---
 src/fabric/test/fabric2_changes_fold_tests.erl | 11 +++
 2 files changed, 22 insertions(+), 7 deletions(-)

diff --git a/src/fabric/src/fabric2_db.erl b/src/fabric/src/fabric2_db.erl
index b3e510b..a310470 100644
--- a/src/fabric/src/fabric2_db.erl
+++ b/src/fabric/src/fabric2_db.erl
@@ -1093,14 +1093,18 @@ fold_changes(Db, SinceSeq, UserFun, UserAcc, Options) ->
 end,
 
 StartKey = get_since_seq(TxDb, Dir, SinceSeq),
-EndKey = case Dir of
-rev -> fabric2_util:seq_zero_vs();
-_ -> fabric2_util:seq_max_vs()
+EndKey = case fabric2_util:get_value(end_key, Options) of
+undefined when Dir == rev ->
+fabric2_util:seq_zero_vs();
+undefined ->
+fabric2_util:seq_max_vs();
+EK when is_binary(EK) ->
+fabric2_fdb:seq_to_vs(EK);
+EK when is_tuple(EK), element(1, EK) == versionstamp ->
+EK
 end,
-FoldOpts = [
-{start_key, StartKey},
-{end_key, EndKey}
-] ++ RestartTx ++ Options,
+BaseOpts = [{start_key, StartKey}] ++ RestartTx ++ Options,
+FoldOpts = lists:keystore(end_key, 1, BaseOpts, {end_key, EndKey}),
 
 {ok, fabric2_fdb:fold_range(TxDb, Prefix, fun({K, V}, Acc) ->
 {SeqVS} = erlfdb_tuple:unpack(K, Prefix),
diff --git a/src/fabric/test/fabric2_changes_fold_tests.erl 
b/src/fabric/test/fabric2_changes_fold_tests.erl
index 8541d97..fa79f25 100644
--- a/src/fabric/test/fabric2_changes_fold_tests.erl
+++ b/src/fabric/test/fabric2_changes_fold_tests.erl
@@ -40,6 +40,7 @@ changes_fold_test_() ->
 ?TDEF_FE(fold_changes_basic_rev),
 ?TDEF_FE(fold_changes_since_now_rev),
 ?TDEF_FE(fold_changes_since_seq_rev),
+?TDEF_FE(fold_changes_with_end_key),
 ?TDEF_FE(fold_changes_basic_tx_too_old),
 ?TDEF_FE(fold_changes_reverse_tx_too_old),
 ?TDEF_FE(fold_changes_tx_too_old_with_single_row_emits),
@@ -124,6 +125,16 @@ fold_changes_since_seq_rev({Db, DocRows}) ->
 fold_changes_since_seq_rev({Db, RestRows}).
 
 
+fold_changes_with_end_key({Db, DocRows}) ->
+lists:foldl(fun(DocRow, Acc) ->
+EndSeq = maps:get(sequence, DocRow),
+Changes = changes(Db, 0, [{end_key, EndSeq}]),
+NewAcc = [DocRow | Acc],
+?assertEqual(Changes, NewAcc),
+NewAcc
+end, [], DocRows).
+
+
 fold_changes_basic_tx_too_old({Db, DocRows0}) ->
 DocRows = lists:reverse(DocRows0),
 



[couchdb] 03/04: Minimize conflicts while building views

2020-11-17 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/couchdb.git

commit 27e8e332cf974bff69b86a8d3c5e2f5a6de4125f
Author: Paul J. Davis 
AuthorDate: Fri Nov 13 14:11:00 2020 -0600

Minimize conflicts while building views

This flips the view indexer to grab the database update_seq outside of
the update transaction. Previously we would cosntantly refresh the
db_seq value on every retry of the transactional loop.

We use a snapshot to get the update_seq so that we don't trigger
spurious read conflicts with any clients that might be updating the
database.
---
 src/couch_views/src/couch_views_indexer.erl   | 54 +++
 src/couch_views/test/couch_views_indexer_test.erl | 45 +++
 2 files changed, 91 insertions(+), 8 deletions(-)

diff --git a/src/couch_views/src/couch_views_indexer.erl 
b/src/couch_views/src/couch_views_indexer.erl
index 2735f66..83ccb2c 100644
--- a/src/couch_views/src/couch_views_indexer.erl
+++ b/src/couch_views/src/couch_views_indexer.erl
@@ -86,15 +86,22 @@ init() ->
 fail_job(Job, Data, sig_changed, "Design document was modified")
 end,
 
+DbSeq = fabric2_fdb:transactional(Db, fun(TxDb) ->
+fabric2_fdb:with_snapshot(TxDb, fun(SSDb) ->
+fabric2_db:get_update_seq(SSDb)
+end)
+end),
+
 State = #{
 tx_db => undefined,
 db_uuid => DbUUID,
-db_seq => undefined,
+db_seq => DbSeq,
 view_seq => undefined,
 last_seq => undefined,
 view_vs => undefined,
 job => Job,
 job_data => Data,
+rows_processed => 0,
 count => 0,
 changes_done => 0,
 doc_acc => [],
@@ -206,8 +213,6 @@ do_update(Db, Mrst0, State0) ->
 {ok, State2} = fold_changes(State1),
 
 #{
-count := Count,
-limit := Limit,
 doc_acc := DocAcc,
 last_seq := LastSeq,
 view_vs := ViewVS,
@@ -228,7 +233,7 @@ do_update(Db, Mrst0, State0) ->
 total_kvs => TotalKVs
 },
 
-case Count < Limit of
+case is_update_finished(State2) of
 true ->
 maybe_set_build_status(TxDb, Mrst2, ViewVS,
 ?INDEX_READY),
@@ -249,6 +254,20 @@ do_update(Db, Mrst0, State0) ->
 end).
 
 
+is_update_finished(State) ->
+#{
+db_seq := DbSeq,
+last_seq := LastSeq,
+view_vs := ViewVs
+} = State,
+AtDbSeq = LastSeq == DbSeq,
+AtViewVs = case ViewVs of
+not_found -> false;
+_ -> LastSeq == fabric2_fdb:vs_to_seq(ViewVs)
+end,
+AtDbSeq orelse AtViewVs.
+
+
 maybe_set_build_status(_TxDb, _Mrst1, not_found, _State) ->
 ok;
 
@@ -258,7 +277,7 @@ maybe_set_build_status(TxDb, Mrst1, _ViewVS, State) ->
 
 % In the first iteration of update we need
 % to populate our db and view sequences
-get_update_start_state(TxDb, Mrst, #{db_seq := undefined} = State) ->
+get_update_start_state(TxDb, Mrst, #{view_seq := undefined} = State) ->
 #{
 view_vs := ViewVS,
 view_seq := ViewSeq
@@ -266,7 +285,6 @@ get_update_start_state(TxDb, Mrst, #{db_seq := undefined} = 
State) ->
 
 State#{
 tx_db := TxDb,
-db_seq := fabric2_db:get_update_seq(TxDb),
 view_vs := ViewVS,
 view_seq := ViewSeq,
 last_seq := ViewSeq
@@ -281,18 +299,36 @@ get_update_start_state(TxDb, _Idx, State) ->
 fold_changes(State) ->
 #{
 view_seq := SinceSeq,
+db_seq := DbSeq,
 limit := Limit,
 tx_db := TxDb
 } = State,
 
+FoldState = State#{
+rows_processed := 0
+},
+
 Fun = fun process_changes/2,
-Opts = [{limit, Limit}, {restart_tx, false}],
-fabric2_db:fold_changes(TxDb, SinceSeq, Fun, State, Opts).
+Opts = [
+{end_key, fabric2_fdb:seq_to_vs(DbSeq)},
+{limit, Limit},
+{restart_tx, false}
+],
+case fabric2_db:fold_changes(TxDb, SinceSeq, Fun, FoldState, Opts) of
+{ok, #{rows_processed := 0} = FinalState} when Limit > 0 ->
+% If we read zero rows with a non-zero limit
+% it means we've caught up to the DbSeq as our
+% last_seq.
+{ok, FinalState#{last_seq := DbSeq}};
+Result ->
+Result
+end.
 
 
 process_changes(Change, Acc) ->
 #{
 doc_acc := DocAcc,
+rows_processed := RowsProcessed,
 count := Count,
 design_opts := DesignOpts,
 view_vs := ViewVS
@@ -308,12 +344,14 @@ process_changes(Change, Acc) ->
 Acc1 = case {Id, IncludeDesign} of
 {<>, false} ->
 maps:merge(Acc, #{
+rows_processed => RowsProcessed + 1,
   

[couchdb] 04/04: Remove unnecessary line wraps

2020-11-17 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/couchdb.git

commit 3168a4dbcef7181b67a989e1d723dc6a93e76280
Author: Paul J. Davis 
AuthorDate: Tue Nov 17 11:23:36 2020 -0600

Remove unnecessary line wraps
---
 src/couch_views/src/couch_views_indexer.erl | 6 ++
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/src/couch_views/src/couch_views_indexer.erl 
b/src/couch_views/src/couch_views_indexer.erl
index 83ccb2c..e3b2ad5 100644
--- a/src/couch_views/src/couch_views_indexer.erl
+++ b/src/couch_views/src/couch_views_indexer.erl
@@ -235,10 +235,8 @@ do_update(Db, Mrst0, State0) ->
 
 case is_update_finished(State2) of
 true ->
-maybe_set_build_status(TxDb, Mrst2, ViewVS,
-?INDEX_READY),
-report_progress(State2#{changes_done := ChangesDone},
-finished),
+maybe_set_build_status(TxDb, Mrst2, ViewVS, ?INDEX_READY),
+report_progress(State2#{changes_done := ChangesDone}, 
finished),
 {Mrst2, finished};
 false ->
 State3 = report_progress(State2, update),



[couchdb] 01/04: Allow snapshots through fabric2_fdb:transactional

2020-11-17 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/couchdb.git

commit 1b30d0810ac0d985676c90dc1b6532f9fb84284c
Author: Paul J. Davis 
AuthorDate: Fri Nov 13 14:08:52 2020 -0600

Allow snapshots through fabric2_fdb:transactional
---
 src/fabric/src/fabric2_fdb.erl |  17 
 src/fabric/test/fabric2_snapshot_tests.erl | 134 +
 2 files changed, 151 insertions(+)

diff --git a/src/fabric/src/fabric2_fdb.erl b/src/fabric/src/fabric2_fdb.erl
index aa2bade..1690f2f 100644
--- a/src/fabric/src/fabric2_fdb.erl
+++ b/src/fabric/src/fabric2_fdb.erl
@@ -18,6 +18,8 @@
 transactional/3,
 transactional/2,
 
+with_snapshot/2,
+
 create/2,
 open/2,
 ensure_current/1,
@@ -150,6 +152,11 @@ transactional(#{tx := undefined} = Db, Fun) ->
 transactional(Db#{reopen => true}, Fun)
 end)
 end;
+transactional(#{tx := {erlfdb_snapshot, _}} = Db, Fun) ->
+DbName = maps:get(name, Db, undefined),
+with_span(Fun, #{'db.name' => DbName}, fun() ->
+Fun(Db)
+end);
 
 transactional(#{tx := {erlfdb_transaction, _}} = Db, Fun) ->
 DbName = maps:get(name, Db, undefined),
@@ -183,6 +190,14 @@ do_transaction(Fun, LayerPrefix) when is_function(Fun, 1) 
->
 end.
 
 
+with_snapshot(#{tx := {erlfdb_transaction, _} = Tx} = TxDb, Fun) ->
+SSDb = TxDb#{tx := erlfdb:snapshot(Tx)},
+Fun(SSDb);
+
+with_snapshot(#{tx := {erlfdb_snapshot, _}} = SSDb, Fun) ->
+Fun(SSDb).
+
+
 create(#{} = Db0, Options) ->
 #{
 name := DbName,
@@ -1865,6 +1880,8 @@ get_db_handle() ->
 end.
 
 
+require_transaction(#{tx := {erlfdb_snapshot, _}} = _Db) ->
+ok;
 require_transaction(#{tx := {erlfdb_transaction, _}} = _Db) ->
 ok;
 require_transaction(#{} = _Db) ->
diff --git a/src/fabric/test/fabric2_snapshot_tests.erl 
b/src/fabric/test/fabric2_snapshot_tests.erl
new file mode 100644
index 000..37ba626
--- /dev/null
+++ b/src/fabric/test/fabric2_snapshot_tests.erl
@@ -0,0 +1,134 @@
+% 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_snapshot_tests).
+
+
+-include_lib("couch/include/couch_db.hrl").
+-include_lib("couch/include/couch_eunit.hrl").
+-include_lib("eunit/include/eunit.hrl").
+-include("fabric2.hrl").
+-include("fabric2_test.hrl").
+
+
+fdb_ss_test_() ->
+{
+"Test snapshot usage",
+setup,
+fun setup/0,
+fun cleanup/1,
+with([
+?TDEF(retry_without_snapshot),
+?TDEF(no_retry_with_snapshot)
+])
+}.
+
+
+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).
+
+
+retry_without_snapshot({Db, _}) ->
+DbName = fabric2_db:name(Db),
+put(retry_count, 0),
+erase(conflict_pid),
+InitDbSeq = fabric2_db:get_update_seq(Db),
+DbSeq = fabric2_fdb:transactional(Db, fun(TxDb) ->
+put(retry_count, get(retry_count) + 1),
+
+% Fetch the update_seq
+Seq = fabric2_db:get_update_seq(TxDb),
+
+% Generate a no-op write so that we don't hit the
+% optimization to skip commits on read-only
+% transactions
+bump_view_size(TxDb),
+
+% Generate a conflicting transaction while
+% we're not yet committed
+case get(conflict_pid) of
+undefined ->
+{Pid, Ref} = spawn_monitor(fun() -> generate_conflict(DbName) 
end),
+receive {'DOWN', Ref, _, _, normal} -> ok end,
+put(conflict_pid, Pid);
+Pid when is_pid(Pid) ->
+ok
+end,
+
+Seq
+end),
+
+?assertEqual(2, get(retry_count)),
+?assertNotEqual(InitDbSeq, DbSeq).
+
+
+no_retry_with_snapshot({Db, _}) ->
+DbName = fabric2_db:name(Db),
+put(retry_count, 0),
+erase(conflict_pid),
+InitDbSeq = fabric2_db:get_update_seq(Db),
+DbSeq = fabric2_fdb:transactional(Db, fun(TxDb) ->
+put(retry_count, get(retry_count) + 1),
+
+% Fetch the update_seq
+Seq = fabric2_fdb:with_snapshot(TxDb, fun(SSDb) ->
+ 

[couchdb] branch main updated (0b98b3b -> 3168a4d)

2020-11-17 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a change to branch main
in repository https://gitbox.apache.org/repos/asf/couchdb.git.


from 0b98b3b  Merge pull request #3274 from cloudant/fix-mango-tests
 new 1b30d08  Allow snapshots through fabric2_fdb:transactional
 new 0e91f2f  Allow specifying an end_key for fold_changes
 new 27e8e33  Minimize conflicts while building views
 new 3168a4d  Remove unnecessary line wraps

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/couch_views/src/couch_views_indexer.erl   |  60 --
 src/couch_views/test/couch_views_indexer_test.erl |  45 
 src/fabric/src/fabric2_db.erl |  18 +--
 src/fabric/src/fabric2_fdb.erl|  17 +++
 src/fabric/test/fabric2_changes_fold_tests.erl|  11 ++
 src/fabric/test/fabric2_snapshot_tests.erl| 134 ++
 6 files changed, 266 insertions(+), 19 deletions(-)
 create mode 100644 src/fabric/test/fabric2_snapshot_tests.erl



[couchdb] 03/04: Minimize conflicts while building views

2020-11-17 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/couchdb.git

commit 27e8e332cf974bff69b86a8d3c5e2f5a6de4125f
Author: Paul J. Davis 
AuthorDate: Fri Nov 13 14:11:00 2020 -0600

Minimize conflicts while building views

This flips the view indexer to grab the database update_seq outside of
the update transaction. Previously we would cosntantly refresh the
db_seq value on every retry of the transactional loop.

We use a snapshot to get the update_seq so that we don't trigger
spurious read conflicts with any clients that might be updating the
database.
---
 src/couch_views/src/couch_views_indexer.erl   | 54 +++
 src/couch_views/test/couch_views_indexer_test.erl | 45 +++
 2 files changed, 91 insertions(+), 8 deletions(-)

diff --git a/src/couch_views/src/couch_views_indexer.erl 
b/src/couch_views/src/couch_views_indexer.erl
index 2735f66..83ccb2c 100644
--- a/src/couch_views/src/couch_views_indexer.erl
+++ b/src/couch_views/src/couch_views_indexer.erl
@@ -86,15 +86,22 @@ init() ->
 fail_job(Job, Data, sig_changed, "Design document was modified")
 end,
 
+DbSeq = fabric2_fdb:transactional(Db, fun(TxDb) ->
+fabric2_fdb:with_snapshot(TxDb, fun(SSDb) ->
+fabric2_db:get_update_seq(SSDb)
+end)
+end),
+
 State = #{
 tx_db => undefined,
 db_uuid => DbUUID,
-db_seq => undefined,
+db_seq => DbSeq,
 view_seq => undefined,
 last_seq => undefined,
 view_vs => undefined,
 job => Job,
 job_data => Data,
+rows_processed => 0,
 count => 0,
 changes_done => 0,
 doc_acc => [],
@@ -206,8 +213,6 @@ do_update(Db, Mrst0, State0) ->
 {ok, State2} = fold_changes(State1),
 
 #{
-count := Count,
-limit := Limit,
 doc_acc := DocAcc,
 last_seq := LastSeq,
 view_vs := ViewVS,
@@ -228,7 +233,7 @@ do_update(Db, Mrst0, State0) ->
 total_kvs => TotalKVs
 },
 
-case Count < Limit of
+case is_update_finished(State2) of
 true ->
 maybe_set_build_status(TxDb, Mrst2, ViewVS,
 ?INDEX_READY),
@@ -249,6 +254,20 @@ do_update(Db, Mrst0, State0) ->
 end).
 
 
+is_update_finished(State) ->
+#{
+db_seq := DbSeq,
+last_seq := LastSeq,
+view_vs := ViewVs
+} = State,
+AtDbSeq = LastSeq == DbSeq,
+AtViewVs = case ViewVs of
+not_found -> false;
+_ -> LastSeq == fabric2_fdb:vs_to_seq(ViewVs)
+end,
+AtDbSeq orelse AtViewVs.
+
+
 maybe_set_build_status(_TxDb, _Mrst1, not_found, _State) ->
 ok;
 
@@ -258,7 +277,7 @@ maybe_set_build_status(TxDb, Mrst1, _ViewVS, State) ->
 
 % In the first iteration of update we need
 % to populate our db and view sequences
-get_update_start_state(TxDb, Mrst, #{db_seq := undefined} = State) ->
+get_update_start_state(TxDb, Mrst, #{view_seq := undefined} = State) ->
 #{
 view_vs := ViewVS,
 view_seq := ViewSeq
@@ -266,7 +285,6 @@ get_update_start_state(TxDb, Mrst, #{db_seq := undefined} = 
State) ->
 
 State#{
 tx_db := TxDb,
-db_seq := fabric2_db:get_update_seq(TxDb),
 view_vs := ViewVS,
 view_seq := ViewSeq,
 last_seq := ViewSeq
@@ -281,18 +299,36 @@ get_update_start_state(TxDb, _Idx, State) ->
 fold_changes(State) ->
 #{
 view_seq := SinceSeq,
+db_seq := DbSeq,
 limit := Limit,
 tx_db := TxDb
 } = State,
 
+FoldState = State#{
+rows_processed := 0
+},
+
 Fun = fun process_changes/2,
-Opts = [{limit, Limit}, {restart_tx, false}],
-fabric2_db:fold_changes(TxDb, SinceSeq, Fun, State, Opts).
+Opts = [
+{end_key, fabric2_fdb:seq_to_vs(DbSeq)},
+{limit, Limit},
+{restart_tx, false}
+],
+case fabric2_db:fold_changes(TxDb, SinceSeq, Fun, FoldState, Opts) of
+{ok, #{rows_processed := 0} = FinalState} when Limit > 0 ->
+% If we read zero rows with a non-zero limit
+% it means we've caught up to the DbSeq as our
+% last_seq.
+{ok, FinalState#{last_seq := DbSeq}};
+Result ->
+Result
+end.
 
 
 process_changes(Change, Acc) ->
 #{
 doc_acc := DocAcc,
+rows_processed := RowsProcessed,
 count := Count,
 design_opts := DesignOpts,
 view_vs := ViewVS
@@ -308,12 +344,14 @@ process_changes(Change, Acc) ->
 Acc1 = case {Id, IncludeDesign} of
 {<>, false} ->
 maps:merge(Acc, #{
+rows_processed => RowsProcessed + 1,
   

[couchdb] 01/04: Allow snapshots through fabric2_fdb:transactional

2020-11-17 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/couchdb.git

commit 1b30d0810ac0d985676c90dc1b6532f9fb84284c
Author: Paul J. Davis 
AuthorDate: Fri Nov 13 14:08:52 2020 -0600

Allow snapshots through fabric2_fdb:transactional
---
 src/fabric/src/fabric2_fdb.erl |  17 
 src/fabric/test/fabric2_snapshot_tests.erl | 134 +
 2 files changed, 151 insertions(+)

diff --git a/src/fabric/src/fabric2_fdb.erl b/src/fabric/src/fabric2_fdb.erl
index aa2bade..1690f2f 100644
--- a/src/fabric/src/fabric2_fdb.erl
+++ b/src/fabric/src/fabric2_fdb.erl
@@ -18,6 +18,8 @@
 transactional/3,
 transactional/2,
 
+with_snapshot/2,
+
 create/2,
 open/2,
 ensure_current/1,
@@ -150,6 +152,11 @@ transactional(#{tx := undefined} = Db, Fun) ->
 transactional(Db#{reopen => true}, Fun)
 end)
 end;
+transactional(#{tx := {erlfdb_snapshot, _}} = Db, Fun) ->
+DbName = maps:get(name, Db, undefined),
+with_span(Fun, #{'db.name' => DbName}, fun() ->
+Fun(Db)
+end);
 
 transactional(#{tx := {erlfdb_transaction, _}} = Db, Fun) ->
 DbName = maps:get(name, Db, undefined),
@@ -183,6 +190,14 @@ do_transaction(Fun, LayerPrefix) when is_function(Fun, 1) 
->
 end.
 
 
+with_snapshot(#{tx := {erlfdb_transaction, _} = Tx} = TxDb, Fun) ->
+SSDb = TxDb#{tx := erlfdb:snapshot(Tx)},
+Fun(SSDb);
+
+with_snapshot(#{tx := {erlfdb_snapshot, _}} = SSDb, Fun) ->
+Fun(SSDb).
+
+
 create(#{} = Db0, Options) ->
 #{
 name := DbName,
@@ -1865,6 +1880,8 @@ get_db_handle() ->
 end.
 
 
+require_transaction(#{tx := {erlfdb_snapshot, _}} = _Db) ->
+ok;
 require_transaction(#{tx := {erlfdb_transaction, _}} = _Db) ->
 ok;
 require_transaction(#{} = _Db) ->
diff --git a/src/fabric/test/fabric2_snapshot_tests.erl 
b/src/fabric/test/fabric2_snapshot_tests.erl
new file mode 100644
index 000..37ba626
--- /dev/null
+++ b/src/fabric/test/fabric2_snapshot_tests.erl
@@ -0,0 +1,134 @@
+% 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_snapshot_tests).
+
+
+-include_lib("couch/include/couch_db.hrl").
+-include_lib("couch/include/couch_eunit.hrl").
+-include_lib("eunit/include/eunit.hrl").
+-include("fabric2.hrl").
+-include("fabric2_test.hrl").
+
+
+fdb_ss_test_() ->
+{
+"Test snapshot usage",
+setup,
+fun setup/0,
+fun cleanup/1,
+with([
+?TDEF(retry_without_snapshot),
+?TDEF(no_retry_with_snapshot)
+])
+}.
+
+
+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).
+
+
+retry_without_snapshot({Db, _}) ->
+DbName = fabric2_db:name(Db),
+put(retry_count, 0),
+erase(conflict_pid),
+InitDbSeq = fabric2_db:get_update_seq(Db),
+DbSeq = fabric2_fdb:transactional(Db, fun(TxDb) ->
+put(retry_count, get(retry_count) + 1),
+
+% Fetch the update_seq
+Seq = fabric2_db:get_update_seq(TxDb),
+
+% Generate a no-op write so that we don't hit the
+% optimization to skip commits on read-only
+% transactions
+bump_view_size(TxDb),
+
+% Generate a conflicting transaction while
+% we're not yet committed
+case get(conflict_pid) of
+undefined ->
+{Pid, Ref} = spawn_monitor(fun() -> generate_conflict(DbName) 
end),
+receive {'DOWN', Ref, _, _, normal} -> ok end,
+put(conflict_pid, Pid);
+Pid when is_pid(Pid) ->
+ok
+end,
+
+Seq
+end),
+
+?assertEqual(2, get(retry_count)),
+?assertNotEqual(InitDbSeq, DbSeq).
+
+
+no_retry_with_snapshot({Db, _}) ->
+DbName = fabric2_db:name(Db),
+put(retry_count, 0),
+erase(conflict_pid),
+InitDbSeq = fabric2_db:get_update_seq(Db),
+DbSeq = fabric2_fdb:transactional(Db, fun(TxDb) ->
+put(retry_count, get(retry_count) + 1),
+
+% Fetch the update_seq
+Seq = fabric2_fdb:with_snapshot(TxDb, fun(SSDb) ->
+ 

[couchdb] 02/04: Allow specifying an end_key for fold_changes

2020-11-17 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/couchdb.git

commit 0e91f2f608d4a920b6c22f1fe1eb9e0ea6982d5a
Author: Paul J. Davis 
AuthorDate: Fri Nov 13 15:13:07 2020 -0600

Allow specifying an end_key for fold_changes

This is useful so that read conflicts on the changes feed will
eventually be resolved. Without an end key specified a reader could end
up in an infinite conflict retry loop if there are clients updating
documents in the database.
---
 src/fabric/src/fabric2_db.erl  | 18 +++---
 src/fabric/test/fabric2_changes_fold_tests.erl | 11 +++
 2 files changed, 22 insertions(+), 7 deletions(-)

diff --git a/src/fabric/src/fabric2_db.erl b/src/fabric/src/fabric2_db.erl
index b3e510b..a310470 100644
--- a/src/fabric/src/fabric2_db.erl
+++ b/src/fabric/src/fabric2_db.erl
@@ -1093,14 +1093,18 @@ fold_changes(Db, SinceSeq, UserFun, UserAcc, Options) ->
 end,
 
 StartKey = get_since_seq(TxDb, Dir, SinceSeq),
-EndKey = case Dir of
-rev -> fabric2_util:seq_zero_vs();
-_ -> fabric2_util:seq_max_vs()
+EndKey = case fabric2_util:get_value(end_key, Options) of
+undefined when Dir == rev ->
+fabric2_util:seq_zero_vs();
+undefined ->
+fabric2_util:seq_max_vs();
+EK when is_binary(EK) ->
+fabric2_fdb:seq_to_vs(EK);
+EK when is_tuple(EK), element(1, EK) == versionstamp ->
+EK
 end,
-FoldOpts = [
-{start_key, StartKey},
-{end_key, EndKey}
-] ++ RestartTx ++ Options,
+BaseOpts = [{start_key, StartKey}] ++ RestartTx ++ Options,
+FoldOpts = lists:keystore(end_key, 1, BaseOpts, {end_key, EndKey}),
 
 {ok, fabric2_fdb:fold_range(TxDb, Prefix, fun({K, V}, Acc) ->
 {SeqVS} = erlfdb_tuple:unpack(K, Prefix),
diff --git a/src/fabric/test/fabric2_changes_fold_tests.erl 
b/src/fabric/test/fabric2_changes_fold_tests.erl
index 8541d97..fa79f25 100644
--- a/src/fabric/test/fabric2_changes_fold_tests.erl
+++ b/src/fabric/test/fabric2_changes_fold_tests.erl
@@ -40,6 +40,7 @@ changes_fold_test_() ->
 ?TDEF_FE(fold_changes_basic_rev),
 ?TDEF_FE(fold_changes_since_now_rev),
 ?TDEF_FE(fold_changes_since_seq_rev),
+?TDEF_FE(fold_changes_with_end_key),
 ?TDEF_FE(fold_changes_basic_tx_too_old),
 ?TDEF_FE(fold_changes_reverse_tx_too_old),
 ?TDEF_FE(fold_changes_tx_too_old_with_single_row_emits),
@@ -124,6 +125,16 @@ fold_changes_since_seq_rev({Db, DocRows}) ->
 fold_changes_since_seq_rev({Db, RestRows}).
 
 
+fold_changes_with_end_key({Db, DocRows}) ->
+lists:foldl(fun(DocRow, Acc) ->
+EndSeq = maps:get(sequence, DocRow),
+Changes = changes(Db, 0, [{end_key, EndSeq}]),
+NewAcc = [DocRow | Acc],
+?assertEqual(Changes, NewAcc),
+NewAcc
+end, [], DocRows).
+
+
 fold_changes_basic_tx_too_old({Db, DocRows0}) ->
 DocRows = lists:reverse(DocRows0),
 



[couchdb] 04/04: Remove unnecessary line wraps

2020-11-17 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/couchdb.git

commit 3168a4dbcef7181b67a989e1d723dc6a93e76280
Author: Paul J. Davis 
AuthorDate: Tue Nov 17 11:23:36 2020 -0600

Remove unnecessary line wraps
---
 src/couch_views/src/couch_views_indexer.erl | 6 ++
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/src/couch_views/src/couch_views_indexer.erl 
b/src/couch_views/src/couch_views_indexer.erl
index 83ccb2c..e3b2ad5 100644
--- a/src/couch_views/src/couch_views_indexer.erl
+++ b/src/couch_views/src/couch_views_indexer.erl
@@ -235,10 +235,8 @@ do_update(Db, Mrst0, State0) ->
 
 case is_update_finished(State2) of
 true ->
-maybe_set_build_status(TxDb, Mrst2, ViewVS,
-?INDEX_READY),
-report_progress(State2#{changes_done := ChangesDone},
-finished),
+maybe_set_build_status(TxDb, Mrst2, ViewVS, ?INDEX_READY),
+report_progress(State2#{changes_done := ChangesDone}, 
finished),
 {Mrst2, finished};
 false ->
 State3 = report_progress(State2, update),



[couchdb] branch main updated (0b98b3b -> 3168a4d)

2020-11-17 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a change to branch main
in repository https://gitbox.apache.org/repos/asf/couchdb.git.


from 0b98b3b  Merge pull request #3274 from cloudant/fix-mango-tests
 new 1b30d08  Allow snapshots through fabric2_fdb:transactional
 new 0e91f2f  Allow specifying an end_key for fold_changes
 new 27e8e33  Minimize conflicts while building views
 new 3168a4d  Remove unnecessary line wraps

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/couch_views/src/couch_views_indexer.erl   |  60 --
 src/couch_views/test/couch_views_indexer_test.erl |  45 
 src/fabric/src/fabric2_db.erl |  18 +--
 src/fabric/src/fabric2_fdb.erl|  17 +++
 src/fabric/test/fabric2_changes_fold_tests.erl|  11 ++
 src/fabric/test/fabric2_snapshot_tests.erl| 134 ++
 6 files changed, 266 insertions(+), 19 deletions(-)
 create mode 100644 src/fabric/test/fabric2_snapshot_tests.erl



[couchdb] 02/04: Allow specifying an end_key for fold_changes

2020-11-17 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/couchdb.git

commit 0e91f2f608d4a920b6c22f1fe1eb9e0ea6982d5a
Author: Paul J. Davis 
AuthorDate: Fri Nov 13 15:13:07 2020 -0600

Allow specifying an end_key for fold_changes

This is useful so that read conflicts on the changes feed will
eventually be resolved. Without an end key specified a reader could end
up in an infinite conflict retry loop if there are clients updating
documents in the database.
---
 src/fabric/src/fabric2_db.erl  | 18 +++---
 src/fabric/test/fabric2_changes_fold_tests.erl | 11 +++
 2 files changed, 22 insertions(+), 7 deletions(-)

diff --git a/src/fabric/src/fabric2_db.erl b/src/fabric/src/fabric2_db.erl
index b3e510b..a310470 100644
--- a/src/fabric/src/fabric2_db.erl
+++ b/src/fabric/src/fabric2_db.erl
@@ -1093,14 +1093,18 @@ fold_changes(Db, SinceSeq, UserFun, UserAcc, Options) ->
 end,
 
 StartKey = get_since_seq(TxDb, Dir, SinceSeq),
-EndKey = case Dir of
-rev -> fabric2_util:seq_zero_vs();
-_ -> fabric2_util:seq_max_vs()
+EndKey = case fabric2_util:get_value(end_key, Options) of
+undefined when Dir == rev ->
+fabric2_util:seq_zero_vs();
+undefined ->
+fabric2_util:seq_max_vs();
+EK when is_binary(EK) ->
+fabric2_fdb:seq_to_vs(EK);
+EK when is_tuple(EK), element(1, EK) == versionstamp ->
+EK
 end,
-FoldOpts = [
-{start_key, StartKey},
-{end_key, EndKey}
-] ++ RestartTx ++ Options,
+BaseOpts = [{start_key, StartKey}] ++ RestartTx ++ Options,
+FoldOpts = lists:keystore(end_key, 1, BaseOpts, {end_key, EndKey}),
 
 {ok, fabric2_fdb:fold_range(TxDb, Prefix, fun({K, V}, Acc) ->
 {SeqVS} = erlfdb_tuple:unpack(K, Prefix),
diff --git a/src/fabric/test/fabric2_changes_fold_tests.erl 
b/src/fabric/test/fabric2_changes_fold_tests.erl
index 8541d97..fa79f25 100644
--- a/src/fabric/test/fabric2_changes_fold_tests.erl
+++ b/src/fabric/test/fabric2_changes_fold_tests.erl
@@ -40,6 +40,7 @@ changes_fold_test_() ->
 ?TDEF_FE(fold_changes_basic_rev),
 ?TDEF_FE(fold_changes_since_now_rev),
 ?TDEF_FE(fold_changes_since_seq_rev),
+?TDEF_FE(fold_changes_with_end_key),
 ?TDEF_FE(fold_changes_basic_tx_too_old),
 ?TDEF_FE(fold_changes_reverse_tx_too_old),
 ?TDEF_FE(fold_changes_tx_too_old_with_single_row_emits),
@@ -124,6 +125,16 @@ fold_changes_since_seq_rev({Db, DocRows}) ->
 fold_changes_since_seq_rev({Db, RestRows}).
 
 
+fold_changes_with_end_key({Db, DocRows}) ->
+lists:foldl(fun(DocRow, Acc) ->
+EndSeq = maps:get(sequence, DocRow),
+Changes = changes(Db, 0, [{end_key, EndSeq}]),
+NewAcc = [DocRow | Acc],
+?assertEqual(Changes, NewAcc),
+NewAcc
+end, [], DocRows).
+
+
 fold_changes_basic_tx_too_old({Db, DocRows0}) ->
 DocRows = lists:reverse(DocRows0),
 



[couchdb] 04/04: Remove unnecessary line wraps

2020-11-17 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/couchdb.git

commit 3168a4dbcef7181b67a989e1d723dc6a93e76280
Author: Paul J. Davis 
AuthorDate: Tue Nov 17 11:23:36 2020 -0600

Remove unnecessary line wraps
---
 src/couch_views/src/couch_views_indexer.erl | 6 ++
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/src/couch_views/src/couch_views_indexer.erl 
b/src/couch_views/src/couch_views_indexer.erl
index 83ccb2c..e3b2ad5 100644
--- a/src/couch_views/src/couch_views_indexer.erl
+++ b/src/couch_views/src/couch_views_indexer.erl
@@ -235,10 +235,8 @@ do_update(Db, Mrst0, State0) ->
 
 case is_update_finished(State2) of
 true ->
-maybe_set_build_status(TxDb, Mrst2, ViewVS,
-?INDEX_READY),
-report_progress(State2#{changes_done := ChangesDone},
-finished),
+maybe_set_build_status(TxDb, Mrst2, ViewVS, ?INDEX_READY),
+report_progress(State2#{changes_done := ChangesDone}, 
finished),
 {Mrst2, finished};
 false ->
 State3 = report_progress(State2, update),



[couchdb] 03/04: Minimize conflicts while building views

2020-11-17 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/couchdb.git

commit 27e8e332cf974bff69b86a8d3c5e2f5a6de4125f
Author: Paul J. Davis 
AuthorDate: Fri Nov 13 14:11:00 2020 -0600

Minimize conflicts while building views

This flips the view indexer to grab the database update_seq outside of
the update transaction. Previously we would cosntantly refresh the
db_seq value on every retry of the transactional loop.

We use a snapshot to get the update_seq so that we don't trigger
spurious read conflicts with any clients that might be updating the
database.
---
 src/couch_views/src/couch_views_indexer.erl   | 54 +++
 src/couch_views/test/couch_views_indexer_test.erl | 45 +++
 2 files changed, 91 insertions(+), 8 deletions(-)

diff --git a/src/couch_views/src/couch_views_indexer.erl 
b/src/couch_views/src/couch_views_indexer.erl
index 2735f66..83ccb2c 100644
--- a/src/couch_views/src/couch_views_indexer.erl
+++ b/src/couch_views/src/couch_views_indexer.erl
@@ -86,15 +86,22 @@ init() ->
 fail_job(Job, Data, sig_changed, "Design document was modified")
 end,
 
+DbSeq = fabric2_fdb:transactional(Db, fun(TxDb) ->
+fabric2_fdb:with_snapshot(TxDb, fun(SSDb) ->
+fabric2_db:get_update_seq(SSDb)
+end)
+end),
+
 State = #{
 tx_db => undefined,
 db_uuid => DbUUID,
-db_seq => undefined,
+db_seq => DbSeq,
 view_seq => undefined,
 last_seq => undefined,
 view_vs => undefined,
 job => Job,
 job_data => Data,
+rows_processed => 0,
 count => 0,
 changes_done => 0,
 doc_acc => [],
@@ -206,8 +213,6 @@ do_update(Db, Mrst0, State0) ->
 {ok, State2} = fold_changes(State1),
 
 #{
-count := Count,
-limit := Limit,
 doc_acc := DocAcc,
 last_seq := LastSeq,
 view_vs := ViewVS,
@@ -228,7 +233,7 @@ do_update(Db, Mrst0, State0) ->
 total_kvs => TotalKVs
 },
 
-case Count < Limit of
+case is_update_finished(State2) of
 true ->
 maybe_set_build_status(TxDb, Mrst2, ViewVS,
 ?INDEX_READY),
@@ -249,6 +254,20 @@ do_update(Db, Mrst0, State0) ->
 end).
 
 
+is_update_finished(State) ->
+#{
+db_seq := DbSeq,
+last_seq := LastSeq,
+view_vs := ViewVs
+} = State,
+AtDbSeq = LastSeq == DbSeq,
+AtViewVs = case ViewVs of
+not_found -> false;
+_ -> LastSeq == fabric2_fdb:vs_to_seq(ViewVs)
+end,
+AtDbSeq orelse AtViewVs.
+
+
 maybe_set_build_status(_TxDb, _Mrst1, not_found, _State) ->
 ok;
 
@@ -258,7 +277,7 @@ maybe_set_build_status(TxDb, Mrst1, _ViewVS, State) ->
 
 % In the first iteration of update we need
 % to populate our db and view sequences
-get_update_start_state(TxDb, Mrst, #{db_seq := undefined} = State) ->
+get_update_start_state(TxDb, Mrst, #{view_seq := undefined} = State) ->
 #{
 view_vs := ViewVS,
 view_seq := ViewSeq
@@ -266,7 +285,6 @@ get_update_start_state(TxDb, Mrst, #{db_seq := undefined} = 
State) ->
 
 State#{
 tx_db := TxDb,
-db_seq := fabric2_db:get_update_seq(TxDb),
 view_vs := ViewVS,
 view_seq := ViewSeq,
 last_seq := ViewSeq
@@ -281,18 +299,36 @@ get_update_start_state(TxDb, _Idx, State) ->
 fold_changes(State) ->
 #{
 view_seq := SinceSeq,
+db_seq := DbSeq,
 limit := Limit,
 tx_db := TxDb
 } = State,
 
+FoldState = State#{
+rows_processed := 0
+},
+
 Fun = fun process_changes/2,
-Opts = [{limit, Limit}, {restart_tx, false}],
-fabric2_db:fold_changes(TxDb, SinceSeq, Fun, State, Opts).
+Opts = [
+{end_key, fabric2_fdb:seq_to_vs(DbSeq)},
+{limit, Limit},
+{restart_tx, false}
+],
+case fabric2_db:fold_changes(TxDb, SinceSeq, Fun, FoldState, Opts) of
+{ok, #{rows_processed := 0} = FinalState} when Limit > 0 ->
+% If we read zero rows with a non-zero limit
+% it means we've caught up to the DbSeq as our
+% last_seq.
+{ok, FinalState#{last_seq := DbSeq}};
+Result ->
+Result
+end.
 
 
 process_changes(Change, Acc) ->
 #{
 doc_acc := DocAcc,
+rows_processed := RowsProcessed,
 count := Count,
 design_opts := DesignOpts,
 view_vs := ViewVS
@@ -308,12 +344,14 @@ process_changes(Change, Acc) ->
 Acc1 = case {Id, IncludeDesign} of
 {<>, false} ->
 maps:merge(Acc, #{
+rows_processed => RowsProcessed + 1,
   

[couchdb] branch main updated (0b98b3b -> 3168a4d)

2020-11-17 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a change to branch main
in repository https://gitbox.apache.org/repos/asf/couchdb.git.


from 0b98b3b  Merge pull request #3274 from cloudant/fix-mango-tests
 new 1b30d08  Allow snapshots through fabric2_fdb:transactional
 new 0e91f2f  Allow specifying an end_key for fold_changes
 new 27e8e33  Minimize conflicts while building views
 new 3168a4d  Remove unnecessary line wraps

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/couch_views/src/couch_views_indexer.erl   |  60 --
 src/couch_views/test/couch_views_indexer_test.erl |  45 
 src/fabric/src/fabric2_db.erl |  18 +--
 src/fabric/src/fabric2_fdb.erl|  17 +++
 src/fabric/test/fabric2_changes_fold_tests.erl|  11 ++
 src/fabric/test/fabric2_snapshot_tests.erl| 134 ++
 6 files changed, 266 insertions(+), 19 deletions(-)
 create mode 100644 src/fabric/test/fabric2_snapshot_tests.erl



[couchdb] 01/04: Allow snapshots through fabric2_fdb:transactional

2020-11-17 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/couchdb.git

commit 1b30d0810ac0d985676c90dc1b6532f9fb84284c
Author: Paul J. Davis 
AuthorDate: Fri Nov 13 14:08:52 2020 -0600

Allow snapshots through fabric2_fdb:transactional
---
 src/fabric/src/fabric2_fdb.erl |  17 
 src/fabric/test/fabric2_snapshot_tests.erl | 134 +
 2 files changed, 151 insertions(+)

diff --git a/src/fabric/src/fabric2_fdb.erl b/src/fabric/src/fabric2_fdb.erl
index aa2bade..1690f2f 100644
--- a/src/fabric/src/fabric2_fdb.erl
+++ b/src/fabric/src/fabric2_fdb.erl
@@ -18,6 +18,8 @@
 transactional/3,
 transactional/2,
 
+with_snapshot/2,
+
 create/2,
 open/2,
 ensure_current/1,
@@ -150,6 +152,11 @@ transactional(#{tx := undefined} = Db, Fun) ->
 transactional(Db#{reopen => true}, Fun)
 end)
 end;
+transactional(#{tx := {erlfdb_snapshot, _}} = Db, Fun) ->
+DbName = maps:get(name, Db, undefined),
+with_span(Fun, #{'db.name' => DbName}, fun() ->
+Fun(Db)
+end);
 
 transactional(#{tx := {erlfdb_transaction, _}} = Db, Fun) ->
 DbName = maps:get(name, Db, undefined),
@@ -183,6 +190,14 @@ do_transaction(Fun, LayerPrefix) when is_function(Fun, 1) 
->
 end.
 
 
+with_snapshot(#{tx := {erlfdb_transaction, _} = Tx} = TxDb, Fun) ->
+SSDb = TxDb#{tx := erlfdb:snapshot(Tx)},
+Fun(SSDb);
+
+with_snapshot(#{tx := {erlfdb_snapshot, _}} = SSDb, Fun) ->
+Fun(SSDb).
+
+
 create(#{} = Db0, Options) ->
 #{
 name := DbName,
@@ -1865,6 +1880,8 @@ get_db_handle() ->
 end.
 
 
+require_transaction(#{tx := {erlfdb_snapshot, _}} = _Db) ->
+ok;
 require_transaction(#{tx := {erlfdb_transaction, _}} = _Db) ->
 ok;
 require_transaction(#{} = _Db) ->
diff --git a/src/fabric/test/fabric2_snapshot_tests.erl 
b/src/fabric/test/fabric2_snapshot_tests.erl
new file mode 100644
index 000..37ba626
--- /dev/null
+++ b/src/fabric/test/fabric2_snapshot_tests.erl
@@ -0,0 +1,134 @@
+% 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_snapshot_tests).
+
+
+-include_lib("couch/include/couch_db.hrl").
+-include_lib("couch/include/couch_eunit.hrl").
+-include_lib("eunit/include/eunit.hrl").
+-include("fabric2.hrl").
+-include("fabric2_test.hrl").
+
+
+fdb_ss_test_() ->
+{
+"Test snapshot usage",
+setup,
+fun setup/0,
+fun cleanup/1,
+with([
+?TDEF(retry_without_snapshot),
+?TDEF(no_retry_with_snapshot)
+])
+}.
+
+
+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).
+
+
+retry_without_snapshot({Db, _}) ->
+DbName = fabric2_db:name(Db),
+put(retry_count, 0),
+erase(conflict_pid),
+InitDbSeq = fabric2_db:get_update_seq(Db),
+DbSeq = fabric2_fdb:transactional(Db, fun(TxDb) ->
+put(retry_count, get(retry_count) + 1),
+
+% Fetch the update_seq
+Seq = fabric2_db:get_update_seq(TxDb),
+
+% Generate a no-op write so that we don't hit the
+% optimization to skip commits on read-only
+% transactions
+bump_view_size(TxDb),
+
+% Generate a conflicting transaction while
+% we're not yet committed
+case get(conflict_pid) of
+undefined ->
+{Pid, Ref} = spawn_monitor(fun() -> generate_conflict(DbName) 
end),
+receive {'DOWN', Ref, _, _, normal} -> ok end,
+put(conflict_pid, Pid);
+Pid when is_pid(Pid) ->
+ok
+end,
+
+Seq
+end),
+
+?assertEqual(2, get(retry_count)),
+?assertNotEqual(InitDbSeq, DbSeq).
+
+
+no_retry_with_snapshot({Db, _}) ->
+DbName = fabric2_db:name(Db),
+put(retry_count, 0),
+erase(conflict_pid),
+InitDbSeq = fabric2_db:get_update_seq(Db),
+DbSeq = fabric2_fdb:transactional(Db, fun(TxDb) ->
+put(retry_count, get(retry_count) + 1),
+
+% Fetch the update_seq
+Seq = fabric2_fdb:with_snapshot(TxDb, fun(SSDb) ->
+ 

[couchdb] 02/04: Allow specifying an end_key for fold_changes

2020-11-17 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/couchdb.git

commit 0e91f2f608d4a920b6c22f1fe1eb9e0ea6982d5a
Author: Paul J. Davis 
AuthorDate: Fri Nov 13 15:13:07 2020 -0600

Allow specifying an end_key for fold_changes

This is useful so that read conflicts on the changes feed will
eventually be resolved. Without an end key specified a reader could end
up in an infinite conflict retry loop if there are clients updating
documents in the database.
---
 src/fabric/src/fabric2_db.erl  | 18 +++---
 src/fabric/test/fabric2_changes_fold_tests.erl | 11 +++
 2 files changed, 22 insertions(+), 7 deletions(-)

diff --git a/src/fabric/src/fabric2_db.erl b/src/fabric/src/fabric2_db.erl
index b3e510b..a310470 100644
--- a/src/fabric/src/fabric2_db.erl
+++ b/src/fabric/src/fabric2_db.erl
@@ -1093,14 +1093,18 @@ fold_changes(Db, SinceSeq, UserFun, UserAcc, Options) ->
 end,
 
 StartKey = get_since_seq(TxDb, Dir, SinceSeq),
-EndKey = case Dir of
-rev -> fabric2_util:seq_zero_vs();
-_ -> fabric2_util:seq_max_vs()
+EndKey = case fabric2_util:get_value(end_key, Options) of
+undefined when Dir == rev ->
+fabric2_util:seq_zero_vs();
+undefined ->
+fabric2_util:seq_max_vs();
+EK when is_binary(EK) ->
+fabric2_fdb:seq_to_vs(EK);
+EK when is_tuple(EK), element(1, EK) == versionstamp ->
+EK
 end,
-FoldOpts = [
-{start_key, StartKey},
-{end_key, EndKey}
-] ++ RestartTx ++ Options,
+BaseOpts = [{start_key, StartKey}] ++ RestartTx ++ Options,
+FoldOpts = lists:keystore(end_key, 1, BaseOpts, {end_key, EndKey}),
 
 {ok, fabric2_fdb:fold_range(TxDb, Prefix, fun({K, V}, Acc) ->
 {SeqVS} = erlfdb_tuple:unpack(K, Prefix),
diff --git a/src/fabric/test/fabric2_changes_fold_tests.erl 
b/src/fabric/test/fabric2_changes_fold_tests.erl
index 8541d97..fa79f25 100644
--- a/src/fabric/test/fabric2_changes_fold_tests.erl
+++ b/src/fabric/test/fabric2_changes_fold_tests.erl
@@ -40,6 +40,7 @@ changes_fold_test_() ->
 ?TDEF_FE(fold_changes_basic_rev),
 ?TDEF_FE(fold_changes_since_now_rev),
 ?TDEF_FE(fold_changes_since_seq_rev),
+?TDEF_FE(fold_changes_with_end_key),
 ?TDEF_FE(fold_changes_basic_tx_too_old),
 ?TDEF_FE(fold_changes_reverse_tx_too_old),
 ?TDEF_FE(fold_changes_tx_too_old_with_single_row_emits),
@@ -124,6 +125,16 @@ fold_changes_since_seq_rev({Db, DocRows}) ->
 fold_changes_since_seq_rev({Db, RestRows}).
 
 
+fold_changes_with_end_key({Db, DocRows}) ->
+lists:foldl(fun(DocRow, Acc) ->
+EndSeq = maps:get(sequence, DocRow),
+Changes = changes(Db, 0, [{end_key, EndSeq}]),
+NewAcc = [DocRow | Acc],
+?assertEqual(Changes, NewAcc),
+NewAcc
+end, [], DocRows).
+
+
 fold_changes_basic_tx_too_old({Db, DocRows0}) ->
 DocRows = lists:reverse(DocRows0),
 



[couchdb] 04/04: Remove unnecessary line wraps

2020-11-17 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/couchdb.git

commit 3168a4dbcef7181b67a989e1d723dc6a93e76280
Author: Paul J. Davis 
AuthorDate: Tue Nov 17 11:23:36 2020 -0600

Remove unnecessary line wraps
---
 src/couch_views/src/couch_views_indexer.erl | 6 ++
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/src/couch_views/src/couch_views_indexer.erl 
b/src/couch_views/src/couch_views_indexer.erl
index 83ccb2c..e3b2ad5 100644
--- a/src/couch_views/src/couch_views_indexer.erl
+++ b/src/couch_views/src/couch_views_indexer.erl
@@ -235,10 +235,8 @@ do_update(Db, Mrst0, State0) ->
 
 case is_update_finished(State2) of
 true ->
-maybe_set_build_status(TxDb, Mrst2, ViewVS,
-?INDEX_READY),
-report_progress(State2#{changes_done := ChangesDone},
-finished),
+maybe_set_build_status(TxDb, Mrst2, ViewVS, ?INDEX_READY),
+report_progress(State2#{changes_done := ChangesDone}, 
finished),
 {Mrst2, finished};
 false ->
 State3 = report_progress(State2, update),



[couchdb] 01/04: Allow snapshots through fabric2_fdb:transactional

2020-11-17 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/couchdb.git

commit 1b30d0810ac0d985676c90dc1b6532f9fb84284c
Author: Paul J. Davis 
AuthorDate: Fri Nov 13 14:08:52 2020 -0600

Allow snapshots through fabric2_fdb:transactional
---
 src/fabric/src/fabric2_fdb.erl |  17 
 src/fabric/test/fabric2_snapshot_tests.erl | 134 +
 2 files changed, 151 insertions(+)

diff --git a/src/fabric/src/fabric2_fdb.erl b/src/fabric/src/fabric2_fdb.erl
index aa2bade..1690f2f 100644
--- a/src/fabric/src/fabric2_fdb.erl
+++ b/src/fabric/src/fabric2_fdb.erl
@@ -18,6 +18,8 @@
 transactional/3,
 transactional/2,
 
+with_snapshot/2,
+
 create/2,
 open/2,
 ensure_current/1,
@@ -150,6 +152,11 @@ transactional(#{tx := undefined} = Db, Fun) ->
 transactional(Db#{reopen => true}, Fun)
 end)
 end;
+transactional(#{tx := {erlfdb_snapshot, _}} = Db, Fun) ->
+DbName = maps:get(name, Db, undefined),
+with_span(Fun, #{'db.name' => DbName}, fun() ->
+Fun(Db)
+end);
 
 transactional(#{tx := {erlfdb_transaction, _}} = Db, Fun) ->
 DbName = maps:get(name, Db, undefined),
@@ -183,6 +190,14 @@ do_transaction(Fun, LayerPrefix) when is_function(Fun, 1) 
->
 end.
 
 
+with_snapshot(#{tx := {erlfdb_transaction, _} = Tx} = TxDb, Fun) ->
+SSDb = TxDb#{tx := erlfdb:snapshot(Tx)},
+Fun(SSDb);
+
+with_snapshot(#{tx := {erlfdb_snapshot, _}} = SSDb, Fun) ->
+Fun(SSDb).
+
+
 create(#{} = Db0, Options) ->
 #{
 name := DbName,
@@ -1865,6 +1880,8 @@ get_db_handle() ->
 end.
 
 
+require_transaction(#{tx := {erlfdb_snapshot, _}} = _Db) ->
+ok;
 require_transaction(#{tx := {erlfdb_transaction, _}} = _Db) ->
 ok;
 require_transaction(#{} = _Db) ->
diff --git a/src/fabric/test/fabric2_snapshot_tests.erl 
b/src/fabric/test/fabric2_snapshot_tests.erl
new file mode 100644
index 000..37ba626
--- /dev/null
+++ b/src/fabric/test/fabric2_snapshot_tests.erl
@@ -0,0 +1,134 @@
+% 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_snapshot_tests).
+
+
+-include_lib("couch/include/couch_db.hrl").
+-include_lib("couch/include/couch_eunit.hrl").
+-include_lib("eunit/include/eunit.hrl").
+-include("fabric2.hrl").
+-include("fabric2_test.hrl").
+
+
+fdb_ss_test_() ->
+{
+"Test snapshot usage",
+setup,
+fun setup/0,
+fun cleanup/1,
+with([
+?TDEF(retry_without_snapshot),
+?TDEF(no_retry_with_snapshot)
+])
+}.
+
+
+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).
+
+
+retry_without_snapshot({Db, _}) ->
+DbName = fabric2_db:name(Db),
+put(retry_count, 0),
+erase(conflict_pid),
+InitDbSeq = fabric2_db:get_update_seq(Db),
+DbSeq = fabric2_fdb:transactional(Db, fun(TxDb) ->
+put(retry_count, get(retry_count) + 1),
+
+% Fetch the update_seq
+Seq = fabric2_db:get_update_seq(TxDb),
+
+% Generate a no-op write so that we don't hit the
+% optimization to skip commits on read-only
+% transactions
+bump_view_size(TxDb),
+
+% Generate a conflicting transaction while
+% we're not yet committed
+case get(conflict_pid) of
+undefined ->
+{Pid, Ref} = spawn_monitor(fun() -> generate_conflict(DbName) 
end),
+receive {'DOWN', Ref, _, _, normal} -> ok end,
+put(conflict_pid, Pid);
+Pid when is_pid(Pid) ->
+ok
+end,
+
+Seq
+end),
+
+?assertEqual(2, get(retry_count)),
+?assertNotEqual(InitDbSeq, DbSeq).
+
+
+no_retry_with_snapshot({Db, _}) ->
+DbName = fabric2_db:name(Db),
+put(retry_count, 0),
+erase(conflict_pid),
+InitDbSeq = fabric2_db:get_update_seq(Db),
+DbSeq = fabric2_fdb:transactional(Db, fun(TxDb) ->
+put(retry_count, get(retry_count) + 1),
+
+% Fetch the update_seq
+Seq = fabric2_fdb:with_snapshot(TxDb, fun(SSDb) ->
+ 

[couchdb] 03/04: Minimize conflicts while building views

2020-11-17 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/couchdb.git

commit 27e8e332cf974bff69b86a8d3c5e2f5a6de4125f
Author: Paul J. Davis 
AuthorDate: Fri Nov 13 14:11:00 2020 -0600

Minimize conflicts while building views

This flips the view indexer to grab the database update_seq outside of
the update transaction. Previously we would cosntantly refresh the
db_seq value on every retry of the transactional loop.

We use a snapshot to get the update_seq so that we don't trigger
spurious read conflicts with any clients that might be updating the
database.
---
 src/couch_views/src/couch_views_indexer.erl   | 54 +++
 src/couch_views/test/couch_views_indexer_test.erl | 45 +++
 2 files changed, 91 insertions(+), 8 deletions(-)

diff --git a/src/couch_views/src/couch_views_indexer.erl 
b/src/couch_views/src/couch_views_indexer.erl
index 2735f66..83ccb2c 100644
--- a/src/couch_views/src/couch_views_indexer.erl
+++ b/src/couch_views/src/couch_views_indexer.erl
@@ -86,15 +86,22 @@ init() ->
 fail_job(Job, Data, sig_changed, "Design document was modified")
 end,
 
+DbSeq = fabric2_fdb:transactional(Db, fun(TxDb) ->
+fabric2_fdb:with_snapshot(TxDb, fun(SSDb) ->
+fabric2_db:get_update_seq(SSDb)
+end)
+end),
+
 State = #{
 tx_db => undefined,
 db_uuid => DbUUID,
-db_seq => undefined,
+db_seq => DbSeq,
 view_seq => undefined,
 last_seq => undefined,
 view_vs => undefined,
 job => Job,
 job_data => Data,
+rows_processed => 0,
 count => 0,
 changes_done => 0,
 doc_acc => [],
@@ -206,8 +213,6 @@ do_update(Db, Mrst0, State0) ->
 {ok, State2} = fold_changes(State1),
 
 #{
-count := Count,
-limit := Limit,
 doc_acc := DocAcc,
 last_seq := LastSeq,
 view_vs := ViewVS,
@@ -228,7 +233,7 @@ do_update(Db, Mrst0, State0) ->
 total_kvs => TotalKVs
 },
 
-case Count < Limit of
+case is_update_finished(State2) of
 true ->
 maybe_set_build_status(TxDb, Mrst2, ViewVS,
 ?INDEX_READY),
@@ -249,6 +254,20 @@ do_update(Db, Mrst0, State0) ->
 end).
 
 
+is_update_finished(State) ->
+#{
+db_seq := DbSeq,
+last_seq := LastSeq,
+view_vs := ViewVs
+} = State,
+AtDbSeq = LastSeq == DbSeq,
+AtViewVs = case ViewVs of
+not_found -> false;
+_ -> LastSeq == fabric2_fdb:vs_to_seq(ViewVs)
+end,
+AtDbSeq orelse AtViewVs.
+
+
 maybe_set_build_status(_TxDb, _Mrst1, not_found, _State) ->
 ok;
 
@@ -258,7 +277,7 @@ maybe_set_build_status(TxDb, Mrst1, _ViewVS, State) ->
 
 % In the first iteration of update we need
 % to populate our db and view sequences
-get_update_start_state(TxDb, Mrst, #{db_seq := undefined} = State) ->
+get_update_start_state(TxDb, Mrst, #{view_seq := undefined} = State) ->
 #{
 view_vs := ViewVS,
 view_seq := ViewSeq
@@ -266,7 +285,6 @@ get_update_start_state(TxDb, Mrst, #{db_seq := undefined} = 
State) ->
 
 State#{
 tx_db := TxDb,
-db_seq := fabric2_db:get_update_seq(TxDb),
 view_vs := ViewVS,
 view_seq := ViewSeq,
 last_seq := ViewSeq
@@ -281,18 +299,36 @@ get_update_start_state(TxDb, _Idx, State) ->
 fold_changes(State) ->
 #{
 view_seq := SinceSeq,
+db_seq := DbSeq,
 limit := Limit,
 tx_db := TxDb
 } = State,
 
+FoldState = State#{
+rows_processed := 0
+},
+
 Fun = fun process_changes/2,
-Opts = [{limit, Limit}, {restart_tx, false}],
-fabric2_db:fold_changes(TxDb, SinceSeq, Fun, State, Opts).
+Opts = [
+{end_key, fabric2_fdb:seq_to_vs(DbSeq)},
+{limit, Limit},
+{restart_tx, false}
+],
+case fabric2_db:fold_changes(TxDb, SinceSeq, Fun, FoldState, Opts) of
+{ok, #{rows_processed := 0} = FinalState} when Limit > 0 ->
+% If we read zero rows with a non-zero limit
+% it means we've caught up to the DbSeq as our
+% last_seq.
+{ok, FinalState#{last_seq := DbSeq}};
+Result ->
+Result
+end.
 
 
 process_changes(Change, Acc) ->
 #{
 doc_acc := DocAcc,
+rows_processed := RowsProcessed,
 count := Count,
 design_opts := DesignOpts,
 view_vs := ViewVS
@@ -308,12 +344,14 @@ process_changes(Change, Acc) ->
 Acc1 = case {Id, IncludeDesign} of
 {<>, false} ->
 maps:merge(Acc, #{
+rows_processed => RowsProcessed + 1,
   

[couchdb] branch main updated (0b98b3b -> 3168a4d)

2020-11-17 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a change to branch main
in repository https://gitbox.apache.org/repos/asf/couchdb.git.


from 0b98b3b  Merge pull request #3274 from cloudant/fix-mango-tests
 new 1b30d08  Allow snapshots through fabric2_fdb:transactional
 new 0e91f2f  Allow specifying an end_key for fold_changes
 new 27e8e33  Minimize conflicts while building views
 new 3168a4d  Remove unnecessary line wraps

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/couch_views/src/couch_views_indexer.erl   |  60 --
 src/couch_views/test/couch_views_indexer_test.erl |  45 
 src/fabric/src/fabric2_db.erl |  18 +--
 src/fabric/src/fabric2_fdb.erl|  17 +++
 src/fabric/test/fabric2_changes_fold_tests.erl|  11 ++
 src/fabric/test/fabric2_snapshot_tests.erl| 134 ++
 6 files changed, 266 insertions(+), 19 deletions(-)
 create mode 100644 src/fabric/test/fabric2_snapshot_tests.erl



[couchdb] branch ensure-view-build-progress updated (08352a8 -> 652876a)

2020-11-17 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a change to branch ensure-view-build-progress
in repository https://gitbox.apache.org/repos/asf/couchdb.git.


 discard 08352a8  Remove unnecessary line wraps
 discard 351d13c  Minimize conflicts while building views
 discard 0f7f2a6  Allow specifying an end_key for fold_changes
 discard fc9e7cf  Allow snapshots through fabric2_fdb:transactional
 add b9bf00a  Allow snapshots through fabric2_fdb:transactional
 add 5e28a46  Allow specifying an end_key for fold_changes
 add 9819cb8  Minimize conflicts while building views
 add 652876a  Remove unnecessary line wraps

This update added new revisions after undoing existing revisions.
That is to say, some revisions that were in the old version of the
branch are not in the new version.  This situation occurs
when a user --force pushes a change and generates a repository
containing something like this:

 * -- * -- B -- O -- O -- O   (08352a8)
\
 N -- N -- N   refs/heads/ensure-view-build-progress (652876a)

You should already have received notification emails for all of the O
revisions, and so the following emails describe only the N revisions
from the common base, B.

Any revisions marked "omit" are not gone; other references still
refer to them.  Any revisions marked "discard" are gone forever.

No new revisions were added by this update.

Summary of changes:
 src/couch_views/test/couch_views_indexer_test.erl | 45 +++
 src/fabric/test/fabric2_snapshot_tests.erl|  5 +++
 2 files changed, 50 insertions(+)



[couchdb] branch ensure-view-build-progress updated (7995675 -> 08352a8)

2020-11-17 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a change to branch ensure-view-build-progress
in repository https://gitbox.apache.org/repos/asf/couchdb.git.


 discard 7995675  Remove unnecessary line wraps
 discard feb66d5  Minimize conflicts while building views
 discard b04cdc4  Allow specifying an end_key for fold_changes
 discard 3844f93  Allow snapshots through fabric2_fdb:transactional
 add fc9e7cf  Allow snapshots through fabric2_fdb:transactional
 add 0f7f2a6  Allow specifying an end_key for fold_changes
 add 351d13c  Minimize conflicts while building views
 add 08352a8  Remove unnecessary line wraps

This update added new revisions after undoing existing revisions.
That is to say, some revisions that were in the old version of the
branch are not in the new version.  This situation occurs
when a user --force pushes a change and generates a repository
containing something like this:

 * -- * -- B -- O -- O -- O   (7995675)
\
 N -- N -- N   refs/heads/ensure-view-build-progress (08352a8)

You should already have received notification emails for all of the O
revisions, and so the following emails describe only the N revisions
from the common base, B.

Any revisions marked "omit" are not gone; other references still
refer to them.  Any revisions marked "discard" are gone forever.

No new revisions were added by this update.

Summary of changes:
 src/fabric/src/fabric2_db.erl  |   4 +-
 src/fabric/test/fabric2_changes_fold_tests.erl |  11 +++
 src/fabric/test/fabric2_snapshot_tests.erl | 129 +
 3 files changed, 143 insertions(+), 1 deletion(-)
 create mode 100644 src/fabric/test/fabric2_snapshot_tests.erl



[couchdb] branch ensure-view-build-progress updated (ab5d87e -> 7995675)

2020-11-17 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a change to branch ensure-view-build-progress
in repository https://gitbox.apache.org/repos/asf/couchdb.git.


 discard ab5d87e  Minimize conflicts while building views
 discard 82ff3e0  Allow specifying an end_key for fold_changes
omit 7aa1806  Allow snapshots through fabric2_fdb:transactional
 add 1be2312  Use `req_body` field if present
 add 5cfa4a8  Merge pull request #3268 from cloudant/reuse-json-body
 add 8c21567  Bump erlfdb to v1.2.3
 add 3844f93  Allow snapshots through fabric2_fdb:transactional
 add b04cdc4  Allow specifying an end_key for fold_changes
 add feb66d5  Minimize conflicts while building views
 add 7995675  Remove unnecessary line wraps

This update added new revisions after undoing existing revisions.
That is to say, some revisions that were in the old version of the
branch are not in the new version.  This situation occurs
when a user --force pushes a change and generates a repository
containing something like this:

 * -- * -- B -- O -- O -- O   (ab5d87e)
\
 N -- N -- N   refs/heads/ensure-view-build-progress (7995675)

You should already have received notification emails for all of the O
revisions, and so the following emails describe only the N revisions
from the common base, B.

Any revisions marked "omit" are not gone; other references still
refer to them.  Any revisions marked "discard" are gone forever.

No new revisions were added by this update.

Summary of changes:
 rebar.config.script |  2 +-
 src/couch/src/couch_httpd.erl   |  7 --
 src/couch_views/src/couch_views_indexer.erl | 38 +
 3 files changed, 34 insertions(+), 13 deletions(-)



[couchdb] branch ensure-view-build-progress updated (6baf574 -> ab5d87e)

2020-11-13 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a change to branch ensure-view-build-progress
in repository https://gitbox.apache.org/repos/asf/couchdb.git.


omit 6baf574  Minimize conflicts while building views
 add 82ff3e0  Allow specifying an end_key for fold_changes
 add ab5d87e  Minimize conflicts while building views

This update added new revisions after undoing existing revisions.
That is to say, some revisions that were in the old version of the
branch are not in the new version.  This situation occurs
when a user --force pushes a change and generates a repository
containing something like this:

 * -- * -- B -- O -- O -- O   (6baf574)
\
 N -- N -- N   refs/heads/ensure-view-build-progress (ab5d87e)

You should already have received notification emails for all of the O
revisions, and so the following emails describe only the N revisions
from the common base, B.

Any revisions marked "omit" are not gone; other references still
refer to them.  Any revisions marked "discard" are gone forever.

No new revisions were added by this update.

Summary of changes:
 src/couch_views/src/couch_views_indexer.erl | 61 ++---
 src/fabric/src/fabric2_db.erl   | 16 
 2 files changed, 38 insertions(+), 39 deletions(-)



[couchdb] 02/02: Minimize conflicts while building views

2020-11-13 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a commit to branch ensure-view-build-progress
in repository https://gitbox.apache.org/repos/asf/couchdb.git

commit 6baf57452e2ccb9869c50da93880f0742a11a97b
Author: Paul J. Davis 
AuthorDate: Fri Nov 13 14:11:00 2020 -0600

Minimize conflicts while building views

If a client is continuously updating a database the view engine would
fail to make progress because the last update sequence is continuously
changing and the unbounded changes read would create a conflict to the
maximum versionstamp value used to delineate the end of the changes key
space.

This commits makes two changes to avoid this. First, the current
update_seq is read via snapshot so that it doesn't become a read
conflict if there's an update. This part is fairly straightforward.

The second change reads the changes feed in a snapshot and then manually
adds the read conflict range for the keys that were actually read. This
solves the issue for large view builds while a database is being
updated. However, this does not address the issue when its a single
document being updated repeatedly. Perhaps if we keep track of the last
sequence read and apply that as a limit when updating the view on a
conflict retry?
---
 src/couch_views/src/couch_views_indexer.erl | 37 ++---
 1 file changed, 29 insertions(+), 8 deletions(-)

diff --git a/src/couch_views/src/couch_views_indexer.erl 
b/src/couch_views/src/couch_views_indexer.erl
index 2735f66..9fdbdb2 100644
--- a/src/couch_views/src/couch_views_indexer.erl
+++ b/src/couch_views/src/couch_views_indexer.erl
@@ -264,13 +264,15 @@ get_update_start_state(TxDb, Mrst, #{db_seq := undefined} 
= State) ->
 view_seq := ViewSeq
 } = couch_views_fdb:get_view_state(TxDb, Mrst),
 
-State#{
-tx_db := TxDb,
-db_seq := fabric2_db:get_update_seq(TxDb),
-view_vs := ViewVS,
-view_seq := ViewSeq,
-last_seq := ViewSeq
-};
+fabric2_fdb:with_snapshot(TxDb, fun(SSDb) ->
+State#{
+tx_db := TxDb,
+db_seq := fabric2_db:get_update_seq(SSDb),
+view_vs := ViewVS,
+view_seq := ViewSeq,
+last_seq := ViewSeq
+}
+end);
 
 get_update_start_state(TxDb, _Idx, State) ->
 State#{
@@ -287,7 +289,16 @@ fold_changes(State) ->
 
 Fun = fun process_changes/2,
 Opts = [{limit, Limit}, {restart_tx, false}],
-fabric2_db:fold_changes(TxDb, SinceSeq, Fun, State, Opts).
+Result = fabric2_fdb:with_snapshot(TxDb, fun(SSDb) ->
+fabric2_db:fold_changes(SSDb, SinceSeq, Fun, State, Opts)
+end),
+case Result of
+{ok, #{last_seq := LastSeq}} ->
+set_changes_conflict(TxDb, SinceSeq, 
fabric2_fdb:seq_to_vs(LastSeq));
+_ ->
+ok
+end,
+Result.
 
 
 process_changes(Change, Acc) ->
@@ -597,6 +608,16 @@ fail_job(Job, Data, Error, Reason) ->
 exit(normal).
 
 
+set_changes_conflict(TxDb, StartVS, EndVS) ->
+#{
+tx := Tx,
+db_prefix := DbPrefix
+} = TxDb,
+StartKey = erlfdb_tuple:pack({?DB_CHANGES, StartVS}, DbPrefix),
+EndKey = erlfdb_tuple:pack({?DB_CHANGES, EndVS}, DbPrefix),
+erlfdb:add_read_conflict_range(Tx, StartKey, EndKey).
+
+
 retry_limit() ->
 config:get_integer("couch_views", "retry_limit", 3).
 



[couchdb] 01/02: Allow snapshots through fabric2_fdb:transactional

2020-11-13 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a commit to branch ensure-view-build-progress
in repository https://gitbox.apache.org/repos/asf/couchdb.git

commit 7aa1806fc052c9e770e00596fa53f25cc6dbfb43
Author: Paul J. Davis 
AuthorDate: Fri Nov 13 14:08:52 2020 -0600

Allow snapshots through fabric2_fdb:transactional
---
 src/fabric/src/fabric2_fdb.erl | 17 +
 1 file changed, 17 insertions(+)

diff --git a/src/fabric/src/fabric2_fdb.erl b/src/fabric/src/fabric2_fdb.erl
index aa2bade..1690f2f 100644
--- a/src/fabric/src/fabric2_fdb.erl
+++ b/src/fabric/src/fabric2_fdb.erl
@@ -18,6 +18,8 @@
 transactional/3,
 transactional/2,
 
+with_snapshot/2,
+
 create/2,
 open/2,
 ensure_current/1,
@@ -150,6 +152,11 @@ transactional(#{tx := undefined} = Db, Fun) ->
 transactional(Db#{reopen => true}, Fun)
 end)
 end;
+transactional(#{tx := {erlfdb_snapshot, _}} = Db, Fun) ->
+DbName = maps:get(name, Db, undefined),
+with_span(Fun, #{'db.name' => DbName}, fun() ->
+Fun(Db)
+end);
 
 transactional(#{tx := {erlfdb_transaction, _}} = Db, Fun) ->
 DbName = maps:get(name, Db, undefined),
@@ -183,6 +190,14 @@ do_transaction(Fun, LayerPrefix) when is_function(Fun, 1) 
->
 end.
 
 
+with_snapshot(#{tx := {erlfdb_transaction, _} = Tx} = TxDb, Fun) ->
+SSDb = TxDb#{tx := erlfdb:snapshot(Tx)},
+Fun(SSDb);
+
+with_snapshot(#{tx := {erlfdb_snapshot, _}} = SSDb, Fun) ->
+Fun(SSDb).
+
+
 create(#{} = Db0, Options) ->
 #{
 name := DbName,
@@ -1865,6 +1880,8 @@ get_db_handle() ->
 end.
 
 
+require_transaction(#{tx := {erlfdb_snapshot, _}} = _Db) ->
+ok;
 require_transaction(#{tx := {erlfdb_transaction, _}} = _Db) ->
 ok;
 require_transaction(#{} = _Db) ->



[couchdb] branch ensure-view-build-progress created (now 6baf574)

2020-11-13 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a change to branch ensure-view-build-progress
in repository https://gitbox.apache.org/repos/asf/couchdb.git.


  at 6baf574  Minimize conflicts while building views

This branch includes the following new commits:

 new 7aa1806  Allow snapshots through fabric2_fdb:transactional
 new 6baf574  Minimize conflicts while building views

The 2 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.




[couchdb] branch fix-ebtree-range-clears updated (3828f92 -> e11ab46)

2020-11-12 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a change to branch fix-ebtree-range-clears
in repository https://gitbox.apache.org/repos/asf/couchdb.git.


 discard 3828f92  Avoid deleting UUID keys that start with zeros
 new e11ab46  Avoid deleting UUID keys that start with zeros

This update added new revisions after undoing existing revisions.
That is to say, some revisions that were in the old version of the
branch are not in the new version.  This situation occurs
when a user --force pushes a change and generates a repository
containing something like this:

 * -- * -- B -- O -- O -- O   (3828f92)
\
 N -- N -- N   refs/heads/fix-ebtree-range-clears (e11ab46)

You should already have received notification emails for all of the O
revisions, and so the following emails describe only the N revisions
from the common base, B.

Any revisions marked "omit" are not gone; other references still
refer to them.  Any revisions marked "discard" are gone forever.

The 1 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:



[couchdb] 01/01: Avoid deleting UUID keys that start with zeros

2020-11-12 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a commit to branch fix-ebtree-range-clears
in repository https://gitbox.apache.org/repos/asf/couchdb.git

commit e11ab46a16a2fd9ecef3bc813e2d73a4ff84888d
Author: Paul J. Davis 
AuthorDate: Thu Nov 12 16:57:44 2020 -0600

Avoid deleting UUID keys that start with zeros

Any ebtree that uses chunked key encoding will accidentally wipe out any
nodes that have a UUID with more than one leading zero byte.
---
 src/ebtree/src/ebtree.erl | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/ebtree/src/ebtree.erl b/src/ebtree/src/ebtree.erl
index 31e1fc8..8bfb2ea 100644
--- a/src/ebtree/src/ebtree.erl
+++ b/src/ebtree/src/ebtree.erl
@@ -56,7 +56,7 @@
 -define(META_ORDER, 0).
 
 -define(NODE, 1).
--define(NODE_ROOT_ID, <<0>>).
+-define(NODE_ROOT_ID, <<0:128>>).
 
 -define(underflow(Tree, Node), Tree#tree.min > length(Node#node.members)).
 -define(at_min(Tree, Node), Tree#tree.min == length(Node#node.members)).



[couchdb] 01/01: Avoid deleting UUID keys that start with zeros

2020-11-12 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a commit to branch fix-ebtree-range-clears
in repository https://gitbox.apache.org/repos/asf/couchdb.git

commit 3828f924459899b98d3414e697877839f0df7f75
Author: Paul J. Davis 
AuthorDate: Thu Nov 12 16:57:44 2020 -0600

Avoid deleting UUID keys that start with zeros
---
 src/ebtree/src/ebtree.erl | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/ebtree/src/ebtree.erl b/src/ebtree/src/ebtree.erl
index 31e1fc8..8bfb2ea 100644
--- a/src/ebtree/src/ebtree.erl
+++ b/src/ebtree/src/ebtree.erl
@@ -56,7 +56,7 @@
 -define(META_ORDER, 0).
 
 -define(NODE, 1).
--define(NODE_ROOT_ID, <<0>>).
+-define(NODE_ROOT_ID, <<0:128>>).
 
 -define(underflow(Tree, Node), Tree#tree.min > length(Node#node.members)).
 -define(at_min(Tree, Node), Tree#tree.min == length(Node#node.members)).



[couchdb] branch fix-ebtree-range-clears created (now 3828f92)

2020-11-12 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a change to branch fix-ebtree-range-clears
in repository https://gitbox.apache.org/repos/asf/couchdb.git.


  at 3828f92  Avoid deleting UUID keys that start with zeros

This branch includes the following new commits:

 new 3828f92  Avoid deleting UUID keys that start with zeros

The 1 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.




[couchdb] 03/03: Fix flaky test

2020-11-10 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/couchdb.git

commit 1a138804f692d0e578a7d4a19f9f13099a59a1cd
Author: Paul J. Davis 
AuthorDate: Tue Nov 10 12:46:07 2020 -0600

Fix flaky test

Waiting for the timeout option to be set means we could still sneak in
and grab the old FDB database handle before fabric2_server updated it in
the application environment.

This new approach just waits until the handle has been updated by
watching the value in the application environment directly.
---
 src/fabric/test/fabric2_tx_options_tests.erl | 10 --
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/src/fabric/test/fabric2_tx_options_tests.erl 
b/src/fabric/test/fabric2_tx_options_tests.erl
index b93cc3d..3232922 100644
--- a/src/fabric/test/fabric2_tx_options_tests.erl
+++ b/src/fabric/test/fabric2_tx_options_tests.erl
@@ -84,9 +84,15 @@ can_configure_options_at_runtime(_) ->
 
 meck:reset(erlfdb),
 
+% Wait until after fabric2_server has updated the new fdb handle
+OldDbHandle = get(?PDICT_DB_KEY),
 config:delete("fdb_tx_options", "size_limit", false),
-% Assert that we get a new handle and are setting our default values
-meck:wait(erlfdb, set_option, ['_', timeout, '_'], 4000),
+test_util:wait(fun() ->
+case application:get_env(fabric, db) of
+{ok, OldDbHandle} -> wait;
+{ok, _} -> ok
+end
+end),
 erase(?PDICT_DB_KEY),
 
 {ok, Db1} = fabric2_db:open(DbName, [?ADMIN_CTX]),



[couchdb] 01/03: Remove ebtree caching

2020-11-10 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/couchdb.git

commit 8267950dc8055b883e599cd993e688de1cec3ab4
Author: Paul J. Davis 
AuthorDate: Tue Nov 10 11:44:53 2020 -0600

Remove ebtree caching

The ebtree caching layer does not work correctly in conjunction with
FoundationDB transaction retry semantics. If we incorrectly cache nodes
that are not actually read from FoundationDB, a retried transaction will
rely on incorrectly cached state and corrupt the ebtree persisted in
FoundationDB.
---
 src/ebtree/src/ebtree.erl | 130 +++---
 1 file changed, 18 insertions(+), 112 deletions(-)

diff --git a/src/ebtree/src/ebtree.erl b/src/ebtree/src/ebtree.erl
index 97a8203..31e1fc8 100644
--- a/src/ebtree/src/ebtree.erl
+++ b/src/ebtree/src/ebtree.erl
@@ -49,8 +49,7 @@
 collate_fun,
 reduce_fun,
 encode_fun,
-persist_fun,
-cache_fun
+persist_fun
 }).
 
 -define(META, 0).
@@ -93,15 +92,13 @@ open(Db, Prefix, Order, Options) when is_binary(Prefix), 
is_integer(Order), Orde
 CollateFun = proplists:get_value(collate_fun, Options, fun collate_raw/2),
 EncodeFun = proplists:get_value(encode_fun, Options, fun encode_erlang/3),
 PersistFun = proplists:get_value(persist_fun, Options, fun 
simple_persist/3),
-CacheFun = proplists:get_value(cache_fun, Options, fun cache_noop/2),
 
 Tree = #tree{
 prefix = Prefix,
 reduce_fun = ReduceFun,
 collate_fun = CollateFun,
 encode_fun = EncodeFun,
-persist_fun = PersistFun,
-cache_fun = CacheFun
+persist_fun = PersistFun
 },
 
 erlfdb:transactional(Db, fun(Tx) ->
@@ -607,10 +604,9 @@ split_child(Tx, #tree{} = Tree, #node{} = Parent0, #node{} 
= Child) ->
 umerge_members(Tree, Parent0#node.level, [{FirstRightKey, 
LastRightKey, RightId, RightReduction}],
 lists:keydelete(Child#node.id, 3, Parent0#node.members)))
 },
-Parent2 = new_node_id_if_cacheable(Tx, Tree, Parent0, Parent1),
 clear_node(Tx, Tree, Child),
-set_nodes(Tx, Tree, [LeftChild, RightChild, Parent2]),
-{Parent2, LeftChild, RightChild}.
+set_nodes(Tx, Tree, [LeftChild, RightChild, Parent1]),
+{Parent1, LeftChild, RightChild}.
 
 
 update_prev_neighbour(_Tx, #tree{} = _Tree, #node{prev = undefined} = _Node) ->
@@ -634,7 +630,7 @@ insert_nonfull(Tx, #tree{} = Tree, #node{level = 0} = 
Node0, Key, Value) ->
 members = umerge_members(Tree, 0, [{Key, Value}], Node0#node.members)
 },
 set_node(Tx, Tree, Node0, Node1),
-{Node1#node.id, reduce_node(Tree, Node1)};
+reduce_node(Tree, Node1);
 
 insert_nonfull(Tx, #tree{} = Tree, #node{} = Node0, Key, Value) ->
 ChildId0 = find_child_id(Tree, Node0, Key),
@@ -654,17 +650,16 @@ insert_nonfull(Tx, #tree{} = Tree, #node{} = Node0, Key, 
Value) ->
 {Node0, Child0}
 end,
 ChildId1 = Child1#node.id,
-{ChildId2, NewReduction} = insert_nonfull(Tx, Tree, Child1, Key, Value),
+NewReduction = insert_nonfull(Tx, Tree, Child1, Key, Value),
 {CurrentFirstKey, CurrentLastKey, ChildId1, _OldReduction} = 
lists:keyfind(ChildId1, 3, Node1#node.members),
 [NewFirstKey, _] = sort_keys(Tree, [Key, CurrentFirstKey]),
 [_, NewLastKey] = sort_keys(Tree, [Key, CurrentLastKey]),
 Node2 = Node1#node{
 members = lists:keyreplace(ChildId1, 3, Node1#node.members,
-{NewFirstKey, NewLastKey, ChildId2, NewReduction})
+{NewFirstKey, NewLastKey, ChildId1, NewReduction})
 },
-Node3 = new_node_id_if_cacheable(Tx, Tree, Node0, Node2),
-set_node(Tx, Tree, Node0, Node3),
-{Node3#node.id, reduce_node(Tree, Node2)}.
+set_node(Tx, Tree, Node0, Node2),
+reduce_node(Tree, Node2).
 
 
 %% @doc Inserts or updates multiple values in the ebtree
@@ -724,14 +719,8 @@ split_node_multi(Tx, Tree, Node) ->
 true when Node#node.id == ?NODE_ROOT_ID ->
 Node#node.members;
 true ->
-NewNode = case node_is_cacheable(Node) of
-true ->
-Node#node{id = new_node_id()};
-false ->
-Node
-end,
-set_node(Tx, Tree, NewNode),
-[to_member(Tree, NewNode)];
+set_node(Tx, Tree, Node),
+[to_member(Tree, Node)];
 false ->
 clear_node(Tx, Tree, Node),
 Nodes0 = create_nodes(Tx, Tree, Node),
@@ -883,18 +872,16 @@ delete(Tx, #tree{} = Tree, #node{} = Parent0, Key) ->
 Parent1 = Parent0#node{
 members = Members3
 },
-Parent2 = new_node_id_if_cacheable(Tx, Tree, Parent0, Parent1),
 clear_nodes(Tx, Tree, [Child0, Sibling]),
 set_nodes(Tx, Tree, NewNodes),
-Parent

[couchdb] 02/03: Remove use of caching

2020-11-10 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/couchdb.git

commit 7d3caa97b18a8bd953c96b39c9a986a4a11e5f34
Author: Paul J. Davis 
AuthorDate: Tue Nov 10 11:52:17 2020 -0600

Remove use of caching

Turns out that ebtree caching wasn't quite correct so removing it for
now.
---
 src/couch_views/src/couch_views_trees.erl | 28 +---
 1 file changed, 1 insertion(+), 27 deletions(-)

diff --git a/src/couch_views/src/couch_views_trees.erl 
b/src/couch_views/src/couch_views_trees.erl
index 236e89f..51c1e46 100644
--- a/src/couch_views/src/couch_views_trees.erl
+++ b/src/couch_views/src/couch_views_trees.erl
@@ -229,7 +229,6 @@ open_id_tree(TxDb, Sig) ->
 Prefix = id_tree_prefix(DbPrefix, Sig),
 TreeOpts = [
 {persist_fun, fun couch_views_fdb:persist_chunks/3},
-{cache_fun, create_cache_fun(id_tree)},
 {encode_fun, create_encode_fun(TxDb)}
 ],
 ebtree:open(Tx, Prefix, get_order(id_btree), TreeOpts).
@@ -255,8 +254,7 @@ open_view_tree(TxDb, Sig, Lang, View, Options) ->
 [{reduce_fun, RedFun}];
 false ->
 [
-{reduce_fun, make_reduce_fun(Lang, View)},
-{cache_fun, create_cache_fun({view, ViewId})}
+{reduce_fun, make_reduce_fun(Lang, View)}
 ]
 end,
 TreeOpts = BaseOpts ++ ExtraOpts,
@@ -333,30 +331,6 @@ make_reduce_fun(Lang, #mrview{} = View) ->
 end.
 
 
-create_cache_fun(TreeId) ->
-CacheTid = case get(TreeId) of
-undefined ->
-Tid = ets:new(?MODULE, [protected, set]),
-put(TreeId, {ebtree_cache, Tid}),
-Tid;
-{ebtree_cache, Tid} ->
-Tid
-end,
-fun
-(set, [Id, Node]) ->
-true = ets:insert_new(CacheTid, {Id, Node}),
-ok;
-(clear, Id) ->
-ets:delete(CacheTid, Id),
-ok;
-(get, Id) ->
-case ets:lookup(CacheTid, Id) of
-[{Id, Node}] -> Node;
-[] -> undefined
-end
-end.
-
-
 create_encode_fun(TxDb) ->
 fun
 (encode, Key, Term) ->



[couchdb] branch main updated (647fd16 -> 1a13880)

2020-11-10 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a change to branch main
in repository https://gitbox.apache.org/repos/asf/couchdb.git.


from 647fd16  Merge pull request #3244 from apache/aegis_db_info
 new 8267950  Remove ebtree caching
 new 7d3caa9  Remove use of caching
 new 1a13880  Fix flaky test

The 3 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/couch_views/src/couch_views_trees.erl|  28 +-
 src/ebtree/src/ebtree.erl| 130 ---
 src/fabric/test/fabric2_tx_options_tests.erl |  10 ++-
 3 files changed, 27 insertions(+), 141 deletions(-)



[couchdb] branch remove-ebtree-caching updated (7bcb944 -> 2a8b920)

2020-11-10 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a change to branch remove-ebtree-caching
in repository https://gitbox.apache.org/repos/asf/couchdb.git.


 discard 7bcb944  Fix flaky test
 add 2a8b920  Fix flaky test

This update added new revisions after undoing existing revisions.
That is to say, some revisions that were in the old version of the
branch are not in the new version.  This situation occurs
when a user --force pushes a change and generates a repository
containing something like this:

 * -- * -- B -- O -- O -- O   (7bcb944)
\
 N -- N -- N   refs/heads/remove-ebtree-caching (2a8b920)

You should already have received notification emails for all of the O
revisions, and so the following emails describe only the N revisions
from the common base, B.

Any revisions marked "omit" are not gone; other references still
refer to them.  Any revisions marked "discard" are gone forever.

No new revisions were added by this update.

Summary of changes:
 src/fabric/test/fabric2_tx_options_tests.erl | 11 +--
 1 file changed, 9 insertions(+), 2 deletions(-)



[couchdb] branch remove-ebtree-caching updated (107cdeb -> 7bcb944)

2020-11-10 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a change to branch remove-ebtree-caching
in repository https://gitbox.apache.org/repos/asf/couchdb.git.


from 107cdeb  Remove use of caching
 add 7bcb944  Fix flaky test

No new revisions were added by this update.

Summary of changes:
 src/fabric/test/fabric2_tx_options_tests.erl | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)



[couchdb] 01/02: Remove ebtree caching

2020-11-10 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a commit to branch remove-ebtree-caching
in repository https://gitbox.apache.org/repos/asf/couchdb.git

commit 78400b900f971219295b759d0f5b36d4efca75fc
Author: Paul J. Davis 
AuthorDate: Tue Nov 10 11:44:53 2020 -0600

Remove ebtree caching

The ebtree caching layer does not work correctly in conjunction with
FoundationDB transaction retry semantics. If we incorrectly cache nodes
that are not actually read from FoundationDB, a retried transaction will
rely on incorrectly cached state and corrupt the ebtree persisted in
FoundationDB.
---
 src/ebtree/src/ebtree.erl | 130 +++---
 1 file changed, 18 insertions(+), 112 deletions(-)

diff --git a/src/ebtree/src/ebtree.erl b/src/ebtree/src/ebtree.erl
index 97a8203..31e1fc8 100644
--- a/src/ebtree/src/ebtree.erl
+++ b/src/ebtree/src/ebtree.erl
@@ -49,8 +49,7 @@
 collate_fun,
 reduce_fun,
 encode_fun,
-persist_fun,
-cache_fun
+persist_fun
 }).
 
 -define(META, 0).
@@ -93,15 +92,13 @@ open(Db, Prefix, Order, Options) when is_binary(Prefix), 
is_integer(Order), Orde
 CollateFun = proplists:get_value(collate_fun, Options, fun collate_raw/2),
 EncodeFun = proplists:get_value(encode_fun, Options, fun encode_erlang/3),
 PersistFun = proplists:get_value(persist_fun, Options, fun 
simple_persist/3),
-CacheFun = proplists:get_value(cache_fun, Options, fun cache_noop/2),
 
 Tree = #tree{
 prefix = Prefix,
 reduce_fun = ReduceFun,
 collate_fun = CollateFun,
 encode_fun = EncodeFun,
-persist_fun = PersistFun,
-cache_fun = CacheFun
+persist_fun = PersistFun
 },
 
 erlfdb:transactional(Db, fun(Tx) ->
@@ -607,10 +604,9 @@ split_child(Tx, #tree{} = Tree, #node{} = Parent0, #node{} 
= Child) ->
 umerge_members(Tree, Parent0#node.level, [{FirstRightKey, 
LastRightKey, RightId, RightReduction}],
 lists:keydelete(Child#node.id, 3, Parent0#node.members)))
 },
-Parent2 = new_node_id_if_cacheable(Tx, Tree, Parent0, Parent1),
 clear_node(Tx, Tree, Child),
-set_nodes(Tx, Tree, [LeftChild, RightChild, Parent2]),
-{Parent2, LeftChild, RightChild}.
+set_nodes(Tx, Tree, [LeftChild, RightChild, Parent1]),
+{Parent1, LeftChild, RightChild}.
 
 
 update_prev_neighbour(_Tx, #tree{} = _Tree, #node{prev = undefined} = _Node) ->
@@ -634,7 +630,7 @@ insert_nonfull(Tx, #tree{} = Tree, #node{level = 0} = 
Node0, Key, Value) ->
 members = umerge_members(Tree, 0, [{Key, Value}], Node0#node.members)
 },
 set_node(Tx, Tree, Node0, Node1),
-{Node1#node.id, reduce_node(Tree, Node1)};
+reduce_node(Tree, Node1);
 
 insert_nonfull(Tx, #tree{} = Tree, #node{} = Node0, Key, Value) ->
 ChildId0 = find_child_id(Tree, Node0, Key),
@@ -654,17 +650,16 @@ insert_nonfull(Tx, #tree{} = Tree, #node{} = Node0, Key, 
Value) ->
 {Node0, Child0}
 end,
 ChildId1 = Child1#node.id,
-{ChildId2, NewReduction} = insert_nonfull(Tx, Tree, Child1, Key, Value),
+NewReduction = insert_nonfull(Tx, Tree, Child1, Key, Value),
 {CurrentFirstKey, CurrentLastKey, ChildId1, _OldReduction} = 
lists:keyfind(ChildId1, 3, Node1#node.members),
 [NewFirstKey, _] = sort_keys(Tree, [Key, CurrentFirstKey]),
 [_, NewLastKey] = sort_keys(Tree, [Key, CurrentLastKey]),
 Node2 = Node1#node{
 members = lists:keyreplace(ChildId1, 3, Node1#node.members,
-{NewFirstKey, NewLastKey, ChildId2, NewReduction})
+{NewFirstKey, NewLastKey, ChildId1, NewReduction})
 },
-Node3 = new_node_id_if_cacheable(Tx, Tree, Node0, Node2),
-set_node(Tx, Tree, Node0, Node3),
-{Node3#node.id, reduce_node(Tree, Node2)}.
+set_node(Tx, Tree, Node0, Node2),
+reduce_node(Tree, Node2).
 
 
 %% @doc Inserts or updates multiple values in the ebtree
@@ -724,14 +719,8 @@ split_node_multi(Tx, Tree, Node) ->
 true when Node#node.id == ?NODE_ROOT_ID ->
 Node#node.members;
 true ->
-NewNode = case node_is_cacheable(Node) of
-true ->
-Node#node{id = new_node_id()};
-false ->
-Node
-end,
-set_node(Tx, Tree, NewNode),
-[to_member(Tree, NewNode)];
+set_node(Tx, Tree, Node),
+[to_member(Tree, Node)];
 false ->
 clear_node(Tx, Tree, Node),
 Nodes0 = create_nodes(Tx, Tree, Node),
@@ -883,18 +872,16 @@ delete(Tx, #tree{} = Tree, #node{} = Parent0, Key) ->
 Parent1 = Parent0#node{
 members = Members3
 },
-Parent2 = new_node_id_if_cacheable(Tx, Tree, Parent0, Parent1),
 clear_nodes(Tx, Tree, [Child0, Sibling]),
 set_nodes(Tx, Tree, NewNodes),
-  

[couchdb] branch remove-ebtree-caching created (now 107cdeb)

2020-11-10 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a change to branch remove-ebtree-caching
in repository https://gitbox.apache.org/repos/asf/couchdb.git.


  at 107cdeb  Remove use of caching

This branch includes the following new commits:

 new 78400b9  Remove ebtree caching
 new 107cdeb  Remove use of caching

The 2 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.




[couchdb] 02/02: Remove use of caching

2020-11-10 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a commit to branch remove-ebtree-caching
in repository https://gitbox.apache.org/repos/asf/couchdb.git

commit 107cdebd550a3d60d65a741d16a857285127a1ee
Author: Paul J. Davis 
AuthorDate: Tue Nov 10 11:52:17 2020 -0600

Remove use of caching

Turns out that ebtree caching wasn't quite correct so removing it for
now.
---
 src/couch_views/src/couch_views_trees.erl | 28 +---
 1 file changed, 1 insertion(+), 27 deletions(-)

diff --git a/src/couch_views/src/couch_views_trees.erl 
b/src/couch_views/src/couch_views_trees.erl
index 236e89f..51c1e46 100644
--- a/src/couch_views/src/couch_views_trees.erl
+++ b/src/couch_views/src/couch_views_trees.erl
@@ -229,7 +229,6 @@ open_id_tree(TxDb, Sig) ->
 Prefix = id_tree_prefix(DbPrefix, Sig),
 TreeOpts = [
 {persist_fun, fun couch_views_fdb:persist_chunks/3},
-{cache_fun, create_cache_fun(id_tree)},
 {encode_fun, create_encode_fun(TxDb)}
 ],
 ebtree:open(Tx, Prefix, get_order(id_btree), TreeOpts).
@@ -255,8 +254,7 @@ open_view_tree(TxDb, Sig, Lang, View, Options) ->
 [{reduce_fun, RedFun}];
 false ->
 [
-{reduce_fun, make_reduce_fun(Lang, View)},
-{cache_fun, create_cache_fun({view, ViewId})}
+{reduce_fun, make_reduce_fun(Lang, View)}
 ]
 end,
 TreeOpts = BaseOpts ++ ExtraOpts,
@@ -333,30 +331,6 @@ make_reduce_fun(Lang, #mrview{} = View) ->
 end.
 
 
-create_cache_fun(TreeId) ->
-CacheTid = case get(TreeId) of
-undefined ->
-Tid = ets:new(?MODULE, [protected, set]),
-put(TreeId, {ebtree_cache, Tid}),
-Tid;
-{ebtree_cache, Tid} ->
-Tid
-end,
-fun
-(set, [Id, Node]) ->
-true = ets:insert_new(CacheTid, {Id, Node}),
-ok;
-(clear, Id) ->
-ets:delete(CacheTid, Id),
-ok;
-(get, Id) ->
-case ets:lookup(CacheTid, Id) of
-[{Id, Node}] -> Node;
-[] -> undefined
-end
-end.
-
-
 create_encode_fun(TxDb) ->
 fun
 (encode, Key, Term) ->



[couchdb] branch changes_filter_all_docs_oom_main updated (ab01683 -> 2a8ddbd)

2020-11-06 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a change to branch changes_filter_all_docs_oom_main
in repository https://gitbox.apache.org/repos/asf/couchdb.git.


from ab01683  Retry filter_docs sequentially if the patch exceeds couchjs 
stack
 add 2a8ddbd  Add test for splitting filter batches

No new revisions were added by this update.

Summary of changes:
 src/couch/test/eunit/couch_query_servers_tests.erl | 55 ++
 1 file changed, 55 insertions(+)



[couchdb] branch main updated: Allow administrators to optionally encrypt views

2020-11-06 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/couchdb.git


The following commit(s) were added to refs/heads/main by this push:
 new 4b10750  Allow administrators to optionally encrypt views
4b10750 is described below

commit 4b107505e9862af35fe616e12892fdf6cfffb12d
Author: Paul J. Davis 
AuthorDate: Tue Nov 3 12:36:50 2020 -0600

Allow administrators to optionally encrypt views
---
 src/couch_views/src/couch_views_trees.erl | 17 +++--
 1 file changed, 15 insertions(+), 2 deletions(-)

diff --git a/src/couch_views/src/couch_views_trees.erl 
b/src/couch_views/src/couch_views_trees.erl
index ad3660e..236e89f 100644
--- a/src/couch_views/src/couch_views_trees.erl
+++ b/src/couch_views/src/couch_views_trees.erl
@@ -229,7 +229,8 @@ open_id_tree(TxDb, Sig) ->
 Prefix = id_tree_prefix(DbPrefix, Sig),
 TreeOpts = [
 {persist_fun, fun couch_views_fdb:persist_chunks/3},
-{cache_fun, create_cache_fun(id_tree)}
+{cache_fun, create_cache_fun(id_tree)},
+{encode_fun, create_encode_fun(TxDb)}
 ],
 ebtree:open(Tx, Prefix, get_order(id_btree), TreeOpts).
 
@@ -245,7 +246,8 @@ open_view_tree(TxDb, Sig, Lang, View, Options) ->
 Prefix = view_tree_prefix(DbPrefix, Sig, ViewId),
 BaseOpts = [
 {collate_fun, couch_views_util:collate_fun(View)},
-{persist_fun, fun couch_views_fdb:persist_chunks/3}
+{persist_fun, fun couch_views_fdb:persist_chunks/3},
+{encode_fun, create_encode_fun(TxDb)}
 ],
 ExtraOpts = case lists:keyfind(read_only, 1, Options) of
 {read_only, Idx} ->
@@ -355,6 +357,17 @@ create_cache_fun(TreeId) ->
 end.
 
 
+create_encode_fun(TxDb) ->
+fun
+(encode, Key, Term) ->
+Bin = term_to_binary(Term, [compressed, {minor_version, 2}]),
+aegis:encrypt(TxDb, Key, Bin);
+(decode, Key, Ciphertext) ->
+Bin = aegis:decrypt(TxDb, Key, Ciphertext),
+binary_to_term(Bin, [safe])
+end.
+
+
 to_map_opts(Options) ->
 Dir = case lists:keyfind(dir, 1, Options) of
 {dir, D} -> D;



[couchdb] branch feat-aegis-for-views created (now ee335d4)

2020-11-03 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a change to branch feat-aegis-for-views
in repository https://gitbox.apache.org/repos/asf/couchdb.git.


  at ee335d4  Allow administrators to optionally encrypt views

No new revisions were added by this update.



[couchdb] 01/02: Fix empty reduce output to match 3.x behavior

2020-10-21 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/couchdb.git

commit ea80fe379d3548fd4b0e98827c17190fabcfd03b
Author: Paul J. Davis 
AuthorDate: Wed Oct 21 14:42:43 2020 -0500

Fix empty reduce output to match 3.x behavior

Before this change a reduce call that contained no rows would end up
returning the "default" value of the given reduce function which is
whatever it would return when given an empty array as input. This
changes the behavior to return `{"rows": []"}` when there are no
rows in the requested range.
---
 src/couch_views/src/couch_views_trees.erl | 25 +
 src/couch_views/test/couch_views_red_test.erl |  4 ++--
 2 files changed, 7 insertions(+), 22 deletions(-)

diff --git a/src/couch_views/src/couch_views_trees.erl 
b/src/couch_views/src/couch_views_trees.erl
index d9340ad..6c32f97 100644
--- a/src/couch_views/src/couch_views_trees.erl
+++ b/src/couch_views/src/couch_views_trees.erl
@@ -144,15 +144,8 @@ fold_red_idx(TxDb, View, Idx, Options, Callback, Acc0) ->
 Callback(GroupKey, RedValue, WAcc)
 end,
 
-case {GroupKeyFun, Dir} of
-{group_all, fwd} ->
-EBtreeOpts = [
-{dir, fwd},
-{inclusive_end, InclusiveEnd}
-],
-Reduction = ebtree:reduce(Tx, Btree, StartKey, EndKey, EBtreeOpts),
-Wrapper({null, Reduction}, Acc0);
-{F, fwd} when is_function(F) ->
+case Dir of
+fwd ->
 EBtreeOpts = [
 {dir, fwd},
 {inclusive_end, InclusiveEnd}
@@ -167,16 +160,7 @@ fold_red_idx(TxDb, View, Idx, Options, Callback, Acc0) ->
 Acc0,
 EBtreeOpts
 );
-{group_all, rev} ->
-% Start/End keys swapped on purpose because ebtree. Also
-% inclusive_start for same reason.
-EBtreeOpts = [
-{dir, rev},
-{inclusive_start, InclusiveEnd}
-],
-Reduction = ebtree:reduce(Tx, Btree, EndKey, StartKey, EBtreeOpts),
-Wrapper({null, Reduction}, Acc0);
-{F, rev} when is_function(F) ->
+rev ->
 % Start/End keys swapped on purpose because ebtree. Also
 % inclusive_start for same reason.
 EBtreeOpts = [
@@ -404,8 +388,9 @@ to_red_opts(Options) ->
 {Dir, StartKey, EndKey, InclusiveEnd} = to_map_opts(Options),
 
 GroupKeyFun = case lists:keyfind(group_key_fun, 1, Options) of
+{group_key_fun, group_all} -> fun({_Key, _DocId}) -> null end;
 {group_key_fun, GKF} -> GKF;
-false -> fun({_Key, _DocId}) -> global_group end
+false -> fun({_Key, _DocId}) -> null end
 end,
 
 {Dir, StartKey, EndKey, InclusiveEnd, GroupKeyFun}.
diff --git a/src/couch_views/test/couch_views_red_test.erl 
b/src/couch_views/test/couch_views_red_test.erl
index 707611f..84c6473 100644
--- a/src/couch_views/test/couch_views_red_test.erl
+++ b/src/couch_views/test/couch_views_red_test.erl
@@ -213,7 +213,7 @@ should_reduce_empty_range({Db, _}) ->
 end_key => 11
 },
 Result = run_query(Db, <<"baz_count">>, Args),
-Expect = {ok, [row(null, 0)]},
+Expect = {ok, []},
 ?assertEqual(Expect, Result).
 
 
@@ -224,7 +224,7 @@ should_reduce_empty_range_rev({Db, _}) ->
 end_key => 10
 },
 Result = run_query(Db, <<"baz_count">>, Args),
-Expect = {ok, [row(null, 0)]},
+Expect = {ok, []},
 ?assertEqual(Expect, Result).
 
 



[couchdb] branch main updated (2428f0f -> 49399ff)

2020-10-21 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a change to branch main
in repository https://gitbox.apache.org/repos/asf/couchdb.git.


from 2428f0f  update to latest fauxton 1.2.6 (#3134)
 new ea80fe3  Fix empty reduce output to match 3.x behavior
 new 49399ff  Remove debug logging

The 2 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/couch_views/src/couch_views_trees.erl | 28 +--
 src/couch_views/test/couch_views_red_test.erl |  4 ++--
 2 files changed, 7 insertions(+), 25 deletions(-)



[couchdb] 02/02: Remove debug logging

2020-10-21 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/couchdb.git

commit 49399ff4510449793ae3241a09cc546a3f9cb925
Author: Paul J. Davis 
AuthorDate: Wed Oct 21 14:44:47 2020 -0500

Remove debug logging
---
 src/couch_views/src/couch_views_trees.erl | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/src/couch_views/src/couch_views_trees.erl 
b/src/couch_views/src/couch_views_trees.erl
index 6c32f97..ad3660e 100644
--- a/src/couch_views/src/couch_views_trees.erl
+++ b/src/couch_views/src/couch_views_trees.erl
@@ -279,9 +279,6 @@ min_order(V) ->
 
 make_read_only_reduce_fun(Lang, View, NthRed) ->
 RedFuns = [Src || {_, Src} <- View#mrview.reduce_funs],
-if RedFuns /= [] -> ok; true ->
-io:format(standard_error, "~p~n", [process_info(self(), 
current_stacktrace)])
-end,
 LPad = lists:duplicate(NthRed - 1, []),
 RPad = lists:duplicate(length(RedFuns) - NthRed, []),
 FunSrc = lists:nth(NthRed, RedFuns),



[couchdb] branch fix-empty-reduce-output updated (04736c0 -> 9e91891)

2020-10-21 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a change to branch fix-empty-reduce-output
in repository https://gitbox.apache.org/repos/asf/couchdb.git.


 discard 04736c0  Remove debug logging
 discard 4d28a6e  Fix empty reduce output to match 3.x behavior
 new 69f1c60  Fix empty reduce output to match 3.x behavior
 new 9e91891  Remove debug logging

This update added new revisions after undoing existing revisions.
That is to say, some revisions that were in the old version of the
branch are not in the new version.  This situation occurs
when a user --force pushes a change and generates a repository
containing something like this:

 * -- * -- B -- O -- O -- O   (04736c0)
\
 N -- N -- N   refs/heads/fix-empty-reduce-output (9e91891)

You should already have received notification emails for all of the O
revisions, and so the following emails describe only the N revisions
from the common base, B.

Any revisions marked "omit" are not gone; other references still
refer to them.  Any revisions marked "discard" are gone forever.

The 2 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/couch_views/test/couch_views_red_test.erl | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)



[couchdb] 02/02: Remove debug logging

2020-10-21 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a commit to branch fix-empty-reduce-output
in repository https://gitbox.apache.org/repos/asf/couchdb.git

commit 9e918919a40265f2790946f37df453df4ba01d32
Author: Paul J. Davis 
AuthorDate: Wed Oct 21 14:44:47 2020 -0500

Remove debug logging
---
 src/couch_views/src/couch_views_trees.erl | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/src/couch_views/src/couch_views_trees.erl 
b/src/couch_views/src/couch_views_trees.erl
index 6c32f97..ad3660e 100644
--- a/src/couch_views/src/couch_views_trees.erl
+++ b/src/couch_views/src/couch_views_trees.erl
@@ -279,9 +279,6 @@ min_order(V) ->
 
 make_read_only_reduce_fun(Lang, View, NthRed) ->
 RedFuns = [Src || {_, Src} <- View#mrview.reduce_funs],
-if RedFuns /= [] -> ok; true ->
-io:format(standard_error, "~p~n", [process_info(self(), 
current_stacktrace)])
-end,
 LPad = lists:duplicate(NthRed - 1, []),
 RPad = lists:duplicate(length(RedFuns) - NthRed, []),
 FunSrc = lists:nth(NthRed, RedFuns),



[couchdb] 01/02: Fix empty reduce output to match 3.x behavior

2020-10-21 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a commit to branch fix-empty-reduce-output
in repository https://gitbox.apache.org/repos/asf/couchdb.git

commit 69f1c6076fd29a7ef925dbeeb7fef2527ad8b68d
Author: Paul J. Davis 
AuthorDate: Wed Oct 21 14:42:43 2020 -0500

Fix empty reduce output to match 3.x behavior

Before this change a reduce call that contained no rows would end up
returning the "default" value of the given reduce function which is
whatever it would return when given an empty array as input. This
changes the behavior to return `{"rows": []"}` when there are no
rows in the requested range.
---
 src/couch_views/src/couch_views_trees.erl | 25 +
 src/couch_views/test/couch_views_red_test.erl |  4 ++--
 2 files changed, 7 insertions(+), 22 deletions(-)

diff --git a/src/couch_views/src/couch_views_trees.erl 
b/src/couch_views/src/couch_views_trees.erl
index d9340ad..6c32f97 100644
--- a/src/couch_views/src/couch_views_trees.erl
+++ b/src/couch_views/src/couch_views_trees.erl
@@ -144,15 +144,8 @@ fold_red_idx(TxDb, View, Idx, Options, Callback, Acc0) ->
 Callback(GroupKey, RedValue, WAcc)
 end,
 
-case {GroupKeyFun, Dir} of
-{group_all, fwd} ->
-EBtreeOpts = [
-{dir, fwd},
-{inclusive_end, InclusiveEnd}
-],
-Reduction = ebtree:reduce(Tx, Btree, StartKey, EndKey, EBtreeOpts),
-Wrapper({null, Reduction}, Acc0);
-{F, fwd} when is_function(F) ->
+case Dir of
+fwd ->
 EBtreeOpts = [
 {dir, fwd},
 {inclusive_end, InclusiveEnd}
@@ -167,16 +160,7 @@ fold_red_idx(TxDb, View, Idx, Options, Callback, Acc0) ->
 Acc0,
 EBtreeOpts
 );
-{group_all, rev} ->
-% Start/End keys swapped on purpose because ebtree. Also
-% inclusive_start for same reason.
-EBtreeOpts = [
-{dir, rev},
-{inclusive_start, InclusiveEnd}
-],
-Reduction = ebtree:reduce(Tx, Btree, EndKey, StartKey, EBtreeOpts),
-Wrapper({null, Reduction}, Acc0);
-{F, rev} when is_function(F) ->
+rev ->
 % Start/End keys swapped on purpose because ebtree. Also
 % inclusive_start for same reason.
 EBtreeOpts = [
@@ -404,8 +388,9 @@ to_red_opts(Options) ->
 {Dir, StartKey, EndKey, InclusiveEnd} = to_map_opts(Options),
 
 GroupKeyFun = case lists:keyfind(group_key_fun, 1, Options) of
+{group_key_fun, group_all} -> fun({_Key, _DocId}) -> null end;
 {group_key_fun, GKF} -> GKF;
-false -> fun({_Key, _DocId}) -> global_group end
+false -> fun({_Key, _DocId}) -> null end
 end,
 
 {Dir, StartKey, EndKey, InclusiveEnd, GroupKeyFun}.
diff --git a/src/couch_views/test/couch_views_red_test.erl 
b/src/couch_views/test/couch_views_red_test.erl
index 707611f..84c6473 100644
--- a/src/couch_views/test/couch_views_red_test.erl
+++ b/src/couch_views/test/couch_views_red_test.erl
@@ -213,7 +213,7 @@ should_reduce_empty_range({Db, _}) ->
 end_key => 11
 },
 Result = run_query(Db, <<"baz_count">>, Args),
-Expect = {ok, [row(null, 0)]},
+Expect = {ok, []},
 ?assertEqual(Expect, Result).
 
 
@@ -224,7 +224,7 @@ should_reduce_empty_range_rev({Db, _}) ->
 end_key => 10
 },
 Result = run_query(Db, <<"baz_count">>, Args),
-Expect = {ok, [row(null, 0)]},
+Expect = {ok, []},
 ?assertEqual(Expect, Result).
 
 



[couchdb] 02/02: Remove debug logging

2020-10-21 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a commit to branch fix-empty-reduce-output
in repository https://gitbox.apache.org/repos/asf/couchdb.git

commit 04736c03033eb14b337edc4bcaba78af078a9083
Author: Paul J. Davis 
AuthorDate: Wed Oct 21 14:44:47 2020 -0500

Remove debug logging
---
 src/couch_views/src/couch_views_trees.erl | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/src/couch_views/src/couch_views_trees.erl 
b/src/couch_views/src/couch_views_trees.erl
index 6c32f97..ad3660e 100644
--- a/src/couch_views/src/couch_views_trees.erl
+++ b/src/couch_views/src/couch_views_trees.erl
@@ -279,9 +279,6 @@ min_order(V) ->
 
 make_read_only_reduce_fun(Lang, View, NthRed) ->
 RedFuns = [Src || {_, Src} <- View#mrview.reduce_funs],
-if RedFuns /= [] -> ok; true ->
-io:format(standard_error, "~p~n", [process_info(self(), 
current_stacktrace)])
-end,
 LPad = lists:duplicate(NthRed - 1, []),
 RPad = lists:duplicate(length(RedFuns) - NthRed, []),
 FunSrc = lists:nth(NthRed, RedFuns),



[couchdb] 01/02: Fix empty reduce output to match 3.x behavior

2020-10-21 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a commit to branch fix-empty-reduce-output
in repository https://gitbox.apache.org/repos/asf/couchdb.git

commit 4d28a6e9c6c3502c8566265abe761eb1937cb026
Author: Paul J. Davis 
AuthorDate: Wed Oct 21 14:42:43 2020 -0500

Fix empty reduce output to match 3.x behavior

Before this change a reduce call that contained no rows would end up
returning the "default" value of the given reduce function which is
whatever it would return when given an empty array as input. This
changes the behavior to return `{"rows": []"}` when there are no
rows in the requested range.
---
 src/couch_views/src/couch_views_trees.erl | 25 +
 1 file changed, 5 insertions(+), 20 deletions(-)

diff --git a/src/couch_views/src/couch_views_trees.erl 
b/src/couch_views/src/couch_views_trees.erl
index d9340ad..6c32f97 100644
--- a/src/couch_views/src/couch_views_trees.erl
+++ b/src/couch_views/src/couch_views_trees.erl
@@ -144,15 +144,8 @@ fold_red_idx(TxDb, View, Idx, Options, Callback, Acc0) ->
 Callback(GroupKey, RedValue, WAcc)
 end,
 
-case {GroupKeyFun, Dir} of
-{group_all, fwd} ->
-EBtreeOpts = [
-{dir, fwd},
-{inclusive_end, InclusiveEnd}
-],
-Reduction = ebtree:reduce(Tx, Btree, StartKey, EndKey, EBtreeOpts),
-Wrapper({null, Reduction}, Acc0);
-{F, fwd} when is_function(F) ->
+case Dir of
+fwd ->
 EBtreeOpts = [
 {dir, fwd},
 {inclusive_end, InclusiveEnd}
@@ -167,16 +160,7 @@ fold_red_idx(TxDb, View, Idx, Options, Callback, Acc0) ->
 Acc0,
 EBtreeOpts
 );
-{group_all, rev} ->
-% Start/End keys swapped on purpose because ebtree. Also
-% inclusive_start for same reason.
-EBtreeOpts = [
-{dir, rev},
-{inclusive_start, InclusiveEnd}
-],
-Reduction = ebtree:reduce(Tx, Btree, EndKey, StartKey, EBtreeOpts),
-Wrapper({null, Reduction}, Acc0);
-{F, rev} when is_function(F) ->
+rev ->
 % Start/End keys swapped on purpose because ebtree. Also
 % inclusive_start for same reason.
 EBtreeOpts = [
@@ -404,8 +388,9 @@ to_red_opts(Options) ->
 {Dir, StartKey, EndKey, InclusiveEnd} = to_map_opts(Options),
 
 GroupKeyFun = case lists:keyfind(group_key_fun, 1, Options) of
+{group_key_fun, group_all} -> fun({_Key, _DocId}) -> null end;
 {group_key_fun, GKF} -> GKF;
-false -> fun({_Key, _DocId}) -> global_group end
+false -> fun({_Key, _DocId}) -> null end
 end,
 
 {Dir, StartKey, EndKey, InclusiveEnd, GroupKeyFun}.



[couchdb] branch fix-empty-reduce-output created (now 04736c0)

2020-10-21 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a change to branch fix-empty-reduce-output
in repository https://gitbox.apache.org/repos/asf/couchdb.git.


  at 04736c0  Remove debug logging

This branch includes the following new commits:

 new 4d28a6e  Fix empty reduce output to match 3.x behavior
 new 04736c0  Remove debug logging

The 2 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.




[couchdb] branch main updated: Allow for disabling custom reduce functions

2020-10-20 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/couchdb.git


The following commit(s) were added to refs/heads/main by this push:
 new bfda163  Allow for disabling custom reduce functions
bfda163 is described below

commit bfda16348f5c61e274ad5087e4a6407fa8306e0d
Author: Paul J. Davis 
AuthorDate: Mon Oct 12 14:08:01 2020 -0500

Allow for disabling custom reduce functions

This changes allows administators to disable custom JavaScript reduce
functions. Custom reduce functions are notoriously difficult to write
correctly and most of the time when written correctly would be more
efficiently done using an builtin reduce.
---
 rel/overlay/etc/default.ini|   3 +
 src/chttpd/src/chttpd.erl  |   2 +
 src/couch_views/src/couch_views_reader.erl |  10 +-
 src/couch_views/src/couch_views_trees.erl  |   2 +-
 src/couch_views/src/couch_views_util.erl   |  34 +++-
 .../test/couch_views_custom_red_test.erl   | 194 +
 6 files changed, 240 insertions(+), 5 deletions(-)

diff --git a/rel/overlay/etc/default.ini b/rel/overlay/etc/default.ini
index 8970be5..ac4e2fa 100644
--- a/rel/overlay/etc/default.ini
+++ b/rel/overlay/etc/default.ini
@@ -323,6 +323,9 @@ iterations = 10 ; iterations for password hashing
 
 ; Settings for view indexing
 [couch_views]
+; Enable custom reduce functions
+;custom_reduce_enabled = true
+
 ; Maximum acceptors waiting to accept view indexing jobs
 ;max_acceptors = 5
 ;
diff --git a/src/chttpd/src/chttpd.erl b/src/chttpd/src/chttpd.erl
index 1a9b19b..3100694 100644
--- a/src/chttpd/src/chttpd.erl
+++ b/src/chttpd/src/chttpd.erl
@@ -1017,6 +1017,8 @@ error_info(all_workers_died) ->
 "request due to overloading or maintenance mode.">>};
 error_info(not_implemented) ->
 {501, <<"not_implemented">>, <<"this feature is not yet implemented">>};
+error_info({disabled, Reason}) ->
+{501, <<"disabled">>, Reason};
 error_info(timeout) ->
 {500, <<"timeout">>, <<"The request could not be processed in a reasonable"
 " amount of time.">>};
diff --git a/src/couch_views/src/couch_views_reader.erl 
b/src/couch_views/src/couch_views_reader.erl
index 3c58627..35ee8a0 100644
--- a/src/couch_views/src/couch_views_reader.erl
+++ b/src/couch_views/src/couch_views_reader.erl
@@ -245,11 +245,19 @@ get_map_view(Lang, Args, ViewName, Views) ->
 
 get_red_view(Lang, Args, ViewName, Views) ->
 case couch_mrview_util:extract_view(Lang, Args, ViewName, Views) of
-{red, {Idx, Lang, View}, _} -> {Idx, Lang, View};
+{red, {Idx, Lang, View}, _} -> check_red_enabled({Idx, Lang, View});
 _ -> throw({not_found, missing_named_view})
 end.
 
 
+check_red_enabled({Idx, _Lang, View} = Resp) ->
+case lists:nth(Idx, View#mrview.reduce_funs) of
+{_, disabled} ->
+throw({disabled, <<"Custom reduce functions are disabled.">>});
+_ ->
+Resp
+end.
+
 expand_keys_args(#mrargs{keys = undefined} = Args) ->
 [Args];
 
diff --git a/src/couch_views/src/couch_views_trees.erl 
b/src/couch_views/src/couch_views_trees.erl
index b45750b..d9340ad 100644
--- a/src/couch_views/src/couch_views_trees.erl
+++ b/src/couch_views/src/couch_views_trees.erl
@@ -323,7 +323,7 @@ make_read_only_reduce_fun(Lang, View, NthRed) ->
 
 
 make_reduce_fun(Lang, #mrview{} = View) ->
-RedFuns = [Src || {_, Src} <- View#mrview.reduce_funs],
+RedFuns = [Src || {_, Src} <- View#mrview.reduce_funs, Src /= disabled],
 fun
 (KVs0, _ReReduce = false) ->
 KVs1 = expand_dupes(KVs0),
diff --git a/src/couch_views/src/couch_views_util.erl 
b/src/couch_views/src/couch_views_util.erl
index 1e3e4be..7040020 100644
--- a/src/couch_views/src/couch_views_util.erl
+++ b/src/couch_views/src/couch_views_util.erl
@@ -65,7 +65,8 @@ ddoc_to_mrst(DbName, #doc{id=Id, body={Fields}}) ->
 NumViews = fun({_, View}, N) ->
 {View#mrview{id_num = N}, N+1}
 end,
-{Views, _} = lists:mapfoldl(NumViews, 0, lists:sort(dict:to_list(BySrc))),
+{Views0, _} = lists:mapfoldl(NumViews, 0, lists:sort(dict:to_list(BySrc))),
+Views1 = maybe_disable_custom_reduce_funs(Views0),
 
 Language = couch_util:get_value(<<"language">>, Fields, <<"javascript">>),
 Lib = couch_util:get_value(<<"lib">>, RawViews, {[]}),
@@ -74,12 +75,12 @@ ddoc_to_mrst(DbName, #doc{id=Id, body={Fields}}) ->
 db_name=DbName,
 idx_name=Id,
 lib=Lib,
-views=Views,
+views=Views1,
 language=Language,
 desig

[couchdb] branch feat-disable-custom-reduce-functions updated (be2f732 -> dc70576)

2020-10-20 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a change to branch feat-disable-custom-reduce-functions
in repository https://gitbox.apache.org/repos/asf/couchdb.git.


 discard be2f732  Disable custom reduce functions by default
 add dc70576  Allow for disabling custom reduce functions

This update added new revisions after undoing existing revisions.
That is to say, some revisions that were in the old version of the
branch are not in the new version.  This situation occurs
when a user --force pushes a change and generates a repository
containing something like this:

 * -- * -- B -- O -- O -- O   (be2f732)
\
 N -- N -- N   refs/heads/feat-disable-custom-reduce-functions 
(dc70576)

You should already have received notification emails for all of the O
revisions, and so the following emails describe only the N revisions
from the common base, B.

Any revisions marked "omit" are not gone; other references still
refer to them.  Any revisions marked "discard" are gone forever.

No new revisions were added by this update.

Summary of changes:
 rel/overlay/etc/default.ini  | 2 +-
 src/couch_views/src/couch_views_util.erl | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)



[couchdb] branch feat-disable-custom-reduce-functions updated (403bec9 -> be2f732)

2020-10-12 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a change to branch feat-disable-custom-reduce-functions
in repository https://gitbox.apache.org/repos/asf/couchdb.git.


 discard 403bec9  Disable custom reduce functions by default
 add be2f732  Disable custom reduce functions by default

This update added new revisions after undoing existing revisions.
That is to say, some revisions that were in the old version of the
branch are not in the new version.  This situation occurs
when a user --force pushes a change and generates a repository
containing something like this:

 * -- * -- B -- O -- O -- O   (403bec9)
\
 N -- N -- N   refs/heads/feat-disable-custom-reduce-functions 
(be2f732)

You should already have received notification emails for all of the O
revisions, and so the following emails describe only the N revisions
from the common base, B.

Any revisions marked "omit" are not gone; other references still
refer to them.  Any revisions marked "discard" are gone forever.

No new revisions were added by this update.

Summary of changes:
 src/couch_views/test/couch_views_custom_red_test.erl | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)



[couchdb] branch feat-disable-custom-reduce-functions updated (403bec9 -> be2f732)

2020-10-12 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a change to branch feat-disable-custom-reduce-functions
in repository https://gitbox.apache.org/repos/asf/couchdb.git.


 discard 403bec9  Disable custom reduce functions by default
 add be2f732  Disable custom reduce functions by default

This update added new revisions after undoing existing revisions.
That is to say, some revisions that were in the old version of the
branch are not in the new version.  This situation occurs
when a user --force pushes a change and generates a repository
containing something like this:

 * -- * -- B -- O -- O -- O   (403bec9)
\
 N -- N -- N   refs/heads/feat-disable-custom-reduce-functions 
(be2f732)

You should already have received notification emails for all of the O
revisions, and so the following emails describe only the N revisions
from the common base, B.

Any revisions marked "omit" are not gone; other references still
refer to them.  Any revisions marked "discard" are gone forever.

No new revisions were added by this update.

Summary of changes:
 src/couch_views/test/couch_views_custom_red_test.erl | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)



[couchdb] branch feat-disable-custom-reduce-functions updated (9345a71 -> 403bec9)

2020-10-12 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a change to branch feat-disable-custom-reduce-functions
in repository https://gitbox.apache.org/repos/asf/couchdb.git.


 discard 9345a71  Disable custom reduce functions by default
 add 403bec9  Disable custom reduce functions by default

This update added new revisions after undoing existing revisions.
That is to say, some revisions that were in the old version of the
branch are not in the new version.  This situation occurs
when a user --force pushes a change and generates a repository
containing something like this:

 * -- * -- B -- O -- O -- O   (9345a71)
\
 N -- N -- N   refs/heads/feat-disable-custom-reduce-functions 
(403bec9)

You should already have received notification emails for all of the O
revisions, and so the following emails describe only the N revisions
from the common base, B.

Any revisions marked "omit" are not gone; other references still
refer to them.  Any revisions marked "discard" are gone forever.

No new revisions were added by this update.

Summary of changes:
 src/couch_views/src/couch_views_util.erl | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)



[couchdb] branch feat-disable-custom-reduce-functions updated (9345a71 -> 403bec9)

2020-10-12 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a change to branch feat-disable-custom-reduce-functions
in repository https://gitbox.apache.org/repos/asf/couchdb.git.


 discard 9345a71  Disable custom reduce functions by default
 add 403bec9  Disable custom reduce functions by default

This update added new revisions after undoing existing revisions.
That is to say, some revisions that were in the old version of the
branch are not in the new version.  This situation occurs
when a user --force pushes a change and generates a repository
containing something like this:

 * -- * -- B -- O -- O -- O   (9345a71)
\
 N -- N -- N   refs/heads/feat-disable-custom-reduce-functions 
(403bec9)

You should already have received notification emails for all of the O
revisions, and so the following emails describe only the N revisions
from the common base, B.

Any revisions marked "omit" are not gone; other references still
refer to them.  Any revisions marked "discard" are gone forever.

No new revisions were added by this update.

Summary of changes:
 src/couch_views/src/couch_views_util.erl | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)



[couchdb] 01/01: Disable custom reduce functions by default

2020-10-12 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a commit to branch feat-disable-custom-reduce-functions
in repository https://gitbox.apache.org/repos/asf/couchdb.git

commit 9345a71c59e3c9e4b27cc37b8979a097031c6b8c
Author: Paul J. Davis 
AuthorDate: Mon Oct 12 14:08:01 2020 -0500

Disable custom reduce functions by default

This prevents users from creating custom reduce functions. Custom reduce
functions are notoriously difficult to write correctly. This change
disables them by default in the eventual 4.0 release.
---
 rel/overlay/etc/default.ini|   3 +
 src/chttpd/src/chttpd.erl  |   2 +
 src/couch_views/src/couch_views_reader.erl |  10 +-
 src/couch_views/src/couch_views_trees.erl  |   2 +-
 src/couch_views/src/couch_views_util.erl   |  34 +++-
 .../test/couch_views_custom_red_test.erl   | 194 +
 6 files changed, 240 insertions(+), 5 deletions(-)

diff --git a/rel/overlay/etc/default.ini b/rel/overlay/etc/default.ini
index 3a377c7..745a1c9 100644
--- a/rel/overlay/etc/default.ini
+++ b/rel/overlay/etc/default.ini
@@ -325,6 +325,9 @@ iterations = 10 ; iterations for password hashing
 
 ; Settings for view indexing
 [couch_views]
+; Enable custom reduce functions
+;custom_reduce_enabled = false
+
 ; Maximum acceptors waiting to accept view indexing jobs
 ;max_acceptors = 5
 ;
diff --git a/src/chttpd/src/chttpd.erl b/src/chttpd/src/chttpd.erl
index 1a9b19b..3100694 100644
--- a/src/chttpd/src/chttpd.erl
+++ b/src/chttpd/src/chttpd.erl
@@ -1017,6 +1017,8 @@ error_info(all_workers_died) ->
 "request due to overloading or maintenance mode.">>};
 error_info(not_implemented) ->
 {501, <<"not_implemented">>, <<"this feature is not yet implemented">>};
+error_info({disabled, Reason}) ->
+{501, <<"disabled">>, Reason};
 error_info(timeout) ->
 {500, <<"timeout">>, <<"The request could not be processed in a reasonable"
 " amount of time.">>};
diff --git a/src/couch_views/src/couch_views_reader.erl 
b/src/couch_views/src/couch_views_reader.erl
index 3c58627..35ee8a0 100644
--- a/src/couch_views/src/couch_views_reader.erl
+++ b/src/couch_views/src/couch_views_reader.erl
@@ -245,11 +245,19 @@ get_map_view(Lang, Args, ViewName, Views) ->
 
 get_red_view(Lang, Args, ViewName, Views) ->
 case couch_mrview_util:extract_view(Lang, Args, ViewName, Views) of
-{red, {Idx, Lang, View}, _} -> {Idx, Lang, View};
+{red, {Idx, Lang, View}, _} -> check_red_enabled({Idx, Lang, View});
 _ -> throw({not_found, missing_named_view})
 end.
 
 
+check_red_enabled({Idx, _Lang, View} = Resp) ->
+case lists:nth(Idx, View#mrview.reduce_funs) of
+{_, disabled} ->
+throw({disabled, <<"Custom reduce functions are disabled.">>});
+_ ->
+Resp
+end.
+
 expand_keys_args(#mrargs{keys = undefined} = Args) ->
 [Args];
 
diff --git a/src/couch_views/src/couch_views_trees.erl 
b/src/couch_views/src/couch_views_trees.erl
index b45750b..d9340ad 100644
--- a/src/couch_views/src/couch_views_trees.erl
+++ b/src/couch_views/src/couch_views_trees.erl
@@ -323,7 +323,7 @@ make_read_only_reduce_fun(Lang, View, NthRed) ->
 
 
 make_reduce_fun(Lang, #mrview{} = View) ->
-RedFuns = [Src || {_, Src} <- View#mrview.reduce_funs],
+RedFuns = [Src || {_, Src} <- View#mrview.reduce_funs, Src /= disabled],
 fun
 (KVs0, _ReReduce = false) ->
 KVs1 = expand_dupes(KVs0),
diff --git a/src/couch_views/src/couch_views_util.erl 
b/src/couch_views/src/couch_views_util.erl
index 1e3e4be..c4130f4 100644
--- a/src/couch_views/src/couch_views_util.erl
+++ b/src/couch_views/src/couch_views_util.erl
@@ -65,7 +65,8 @@ ddoc_to_mrst(DbName, #doc{id=Id, body={Fields}}) ->
 NumViews = fun({_, View}, N) ->
 {View#mrview{id_num = N}, N+1}
 end,
-{Views, _} = lists:mapfoldl(NumViews, 0, lists:sort(dict:to_list(BySrc))),
+{Views0, _} = lists:mapfoldl(NumViews, 0, lists:sort(dict:to_list(BySrc))),
+Views1 = maybe_filter_custom_reduce_funs(Views0),
 
 Language = couch_util:get_value(<<"language">>, Fields, <<"javascript">>),
 Lib = couch_util:get_value(<<"lib">>, RawViews, {[]}),
@@ -74,12 +75,12 @@ ddoc_to_mrst(DbName, #doc{id=Id, body={Fields}}) ->
 db_name=DbName,
 idx_name=Id,
 lib=Lib,
-views=Views,
+views=Views1,
 language=Language,
 design_opts=DesignOpts,
 partitioned=Partitioned
 },
-SigInfo = {Views, Language, DesignOpts, couch_index_util:sort_lib(Lib)},
+SigInfo = {Views1, Language, DesignOpt

[couchdb] branch feat-disable-custom-reduce-functions created (now 9345a71)

2020-10-12 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a change to branch feat-disable-custom-reduce-functions
in repository https://gitbox.apache.org/repos/asf/couchdb.git.


  at 9345a71  Disable custom reduce functions by default

This branch includes the following new commits:

 new 9345a71  Disable custom reduce functions by default

The 1 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.




[couchdb] 03/08: Reimplement db wide view size tracking

2020-09-30 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/couchdb.git

commit a8cebfa6d3ddbfb6419c83ca7b3b607da330de1a
Author: Paul J. Davis 
AuthorDate: Thu Sep 3 12:05:45 2020 -0500

Reimplement db wide view size tracking
---
 src/couch_views/src/couch_views_fdb.erl|  30 +-
 src/couch_views/src/couch_views_trees.erl  |  27 +-
 src/couch_views/test/couch_views_size_test.erl | 829 +
 3 files changed, 357 insertions(+), 529 deletions(-)

diff --git a/src/couch_views/src/couch_views_fdb.erl 
b/src/couch_views/src/couch_views_fdb.erl
index e813f2b..f238a8f 100644
--- a/src/couch_views/src/couch_views_fdb.erl
+++ b/src/couch_views/src/couch_views_fdb.erl
@@ -25,7 +25,8 @@
 list_signatures/1,
 clear_index/2,
 
-persist_chunks/3
+persist_chunks/3,
+update_kv_size/4
 ]).
 
 -ifdef(TEST).
@@ -135,6 +136,11 @@ clear_index(Db, Signature) ->
 db_prefix := DbPrefix
 } = Db,
 
+% Get view size to remove from global counter
+SizeTuple = {?DB_VIEWS, ?VIEW_INFO, ?VIEW_KV_SIZE, Signature},
+SizeKey = erlfdb_tuple:pack(SizeTuple, DbPrefix),
+ViewSize = ?bin2uint(erlfdb:wait(erlfdb:get(Tx, SizeKey))),
+
 % Clear index info keys
 Keys = [
 {?DB_VIEWS, ?VIEW_INFO, ?VIEW_UPDATE_SEQ, Signature},
@@ -154,7 +160,12 @@ clear_index(Db, Signature) ->
 % Clear tree data
 TreeTuple = {?DB_VIEWS, ?VIEW_TREES, Signature},
 TreePrefix = erlfdb_tuple:pack(TreeTuple, DbPrefix),
-erlfdb:clear_range_startswith(Tx, TreePrefix).
+erlfdb:clear_range_startswith(Tx, TreePrefix),
+
+% Decrement db wide view size counter
+DbSizeTuple = {?DB_STATS, <<"sizes">>, <<"views">>},
+DbSizeKey = erlfdb_tuple:pack(DbSizeTuple, DbPrefix),
+erlfdb:add(Tx, DbSizeKey, -ViewSize).
 
 
 persist_chunks(Tx, set, [Key, Value]) ->
@@ -181,6 +192,21 @@ persist_chunks(Tx, clear, Key) ->
 erlfdb:clear_range_startswith(Tx, Key).
 
 
+update_kv_size(TxDb, Sig, OldSize, NewSize) ->
+#{
+tx := Tx,
+db_prefix := DbPrefix
+} = TxDb,
+
+ViewTuple = {?DB_VIEWS, ?VIEW_INFO, ?VIEW_KV_SIZE, Sig},
+ViewKey = erlfdb_tuple:pack(ViewTuple, DbPrefix),
+erlfdb:set(Tx, ViewKey, ?uint2bin(NewSize)),
+
+DbTuple = {?DB_STATS, <<"sizes">>, <<"views">>},
+DbKey = erlfdb_tuple:pack(DbTuple, DbPrefix),
+erlfdb:add(Tx, DbKey, NewSize - OldSize).
+
+
 seq_key(DbPrefix, Sig) ->
 Key = {?DB_VIEWS, ?VIEW_INFO, ?VIEW_UPDATE_SEQ, Sig},
 erlfdb_tuple:pack(Key, DbPrefix).
diff --git a/src/couch_views/src/couch_views_trees.erl 
b/src/couch_views/src/couch_views_trees.erl
index 0f680a6..7ce3505 100644
--- a/src/couch_views/src/couch_views_trees.erl
+++ b/src/couch_views/src/couch_views_trees.erl
@@ -127,6 +127,12 @@ update_views(TxDb, Mrst, Docs) ->
 tx := Tx
 } = TxDb,
 
+% Get initial KV size
+OldKVSize = lists:foldl(fun(View, SizeAcc) ->
+{_, Size} = ebtree:full_reduce(Tx, View#mrview.btree),
+SizeAcc + Size
+end, 0, Mrst#mrst.views),
+
 % Collect update information
 #{
 ids := IdMap,
@@ -146,7 +152,15 @@ update_views(TxDb, Mrst, Docs) ->
 
 ViewMap = maps:get(ViewId, ViewMaps, #{}),
 update_btree(Tx, BTree, ViewMap, DeleteRef)
-end, Mrst#mrst.views).
+end, Mrst#mrst.views),
+
+% Get new KV size after update
+NewKVSize = lists:foldl(fun(View, SizeAcc) ->
+{_, Size} = ebtree:full_reduce(Tx, View#mrview.btree),
+SizeAcc + Size
+end, 0, Mrst#mrst.views),
+
+couch_views_fdb:update_kv_size(TxDb, Mrst#mrst.sig, OldKVSize, NewKVSize).
 
 
 open_id_tree(TxDb, Sig) ->
@@ -201,15 +215,16 @@ make_reduce_fun(_Lang, #mrview{}) ->
 (KVs, _ReReduce = false) ->
 TotalSize = lists:foldl(fun({{K, _DocId}, V}, Acc) ->
 KSize = couch_ejson_size:encoded_size(K),
-VSize = case V of
+Acc + case V of
 {dups, Dups} ->
 lists:foldl(fun(D, DAcc) ->
-DAcc + couch_ejson_size:encoded_size(D)
+VSize = couch_ejson_size:encoded_size(D),
+DAcc + KSize + VSize
 end, 0, Dups);
 _ ->
-couch_ejson_size:encoded_size(V)
-end,
-KSize + VSize + Acc
+VSize = couch_ejson_size:encoded_size(V),
+KSize + VSize
+end
 end, 0, KVs),
 {length(KVs), TotalSize};
 (KRs, _ReReduce = true) ->
diff --git a/src/couch_views/test/couch_views_size_test.erl 
b/src/couch_views/test/couch_views_size_test.erl
index cc2fe39..e69b5b2 10064

[couchdb] 02/08: Views on ebtree

2020-09-30 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/couchdb.git

commit b91f193563c9b3dadd4f8de4c49de9cbf4304837
Author: Paul J. Davis 
AuthorDate: Fri Jul 24 10:59:05 2020 -0500

Views on ebtree
---
 rel/overlay/etc/default.ini   |   6 +
 src/couch_views/include/couch_views.hrl   |   5 +
 src/couch_views/src/couch_views.erl   |  55 +--
 src/couch_views/src/couch_views_fdb.erl   | 331 ++---
 src/couch_views/src/couch_views_indexer.erl   |  54 +--
 src/couch_views/src/couch_views_reader.erl| 115 +++---
 src/couch_views/src/couch_views_trees.erl | 429 ++
 src/couch_views/src/couch_views_updater.erl   |  13 +-
 src/couch_views/src/couch_views_util.erl  |  35 ++
 src/couch_views/test/couch_views_cleanup_test.erl |   2 +-
 src/couch_views/test/couch_views_indexer_test.erl |  64 ++--
 src/couch_views/test/couch_views_size_test.erl|  25 +-
 src/couch_views/test/couch_views_updater_test.erl |   4 +-
 src/mango/src/mango_cursor_view.erl   |  14 +-
 src/mango/src/mango_idx_view.erl  |   7 +-
 src/mango/src/mango_idx_view.hrl  |  13 +
 16 files changed, 687 insertions(+), 485 deletions(-)

diff --git a/rel/overlay/etc/default.ini b/rel/overlay/etc/default.ini
index abcf0bd..3a377c7 100644
--- a/rel/overlay/etc/default.ini
+++ b/rel/overlay/etc/default.ini
@@ -337,6 +337,12 @@ iterations = 10 ; iterations for password hashing
 ; The maximum allowed value size emitted from a view for a document (in bytes)
 ;value_size_limit = 64000
 ;
+; The maximum size of B+Tree nodes used by the id btree
+;id_btree_node_size = 100
+;
+; The maximum size of B+Tree nodes used by view btrees
+;view_btree_node_size = 100
+;
 ; Batch size sensing parameters
 ; batch_initial_size = 100 ; Initial batch size in number of documents
 ; batch_search_increment = 500 ; Size change when searching for the threshold
diff --git a/src/couch_views/include/couch_views.hrl 
b/src/couch_views/include/couch_views.hrl
index 3d0110f..3882191 100644
--- a/src/couch_views/include/couch_views.hrl
+++ b/src/couch_views/include/couch_views.hrl
@@ -13,6 +13,7 @@
 % Index info/data subspaces
 -define(VIEW_INFO, 0).
 -define(VIEW_DATA, 1).
+-define(VIEW_TREES, 3).
 
 % Index info keys
 -define(VIEW_UPDATE_SEQ, 0).
@@ -25,6 +26,10 @@
 -define(VIEW_ID_RANGE, 0).
 -define(VIEW_MAP_RANGE, 1).
 
+% Tree keys
+-define(VIEW_ID_TREE, 0).
+-define(VIEW_ROW_TREES, 1).
+
 % jobs api
 -define(INDEX_JOB_TYPE, <<"views">>).
 
diff --git a/src/couch_views/src/couch_views.erl 
b/src/couch_views/src/couch_views.erl
index d9ba0c1..da8a142 100644
--- a/src/couch_views/src/couch_views.erl
+++ b/src/couch_views/src/couch_views.erl
@@ -48,11 +48,7 @@ query(Db, DDoc, ViewName, Callback, Acc0, Args0) ->
 Args1 = to_mrargs(Args0),
 Args2 = couch_mrview_util:set_view_type(Args1, ViewName, Views),
 Args3 = couch_mrview_util:validate_args(Args2),
-ok = check_range(Args3),
-case is_reduce_view(Args3) of
-true -> throw(not_implemented);
-false -> ok
-end,
+ok = check_range(Mrst, ViewName, Args3),
 
 try
 fabric2_fdb:transactional(Db, fun(TxDb) ->
@@ -100,9 +96,10 @@ get_info(Db, DDoc) ->
 {ok, Mrst} = couch_views_util:ddoc_to_mrst(DbName, DDoc),
 Sig = fabric2_util:to_hex(Mrst#mrst.sig),
 {UpdateSeq, DataSize, Status} = fabric2_fdb:transactional(Db, fun(TxDb) ->
-Seq = couch_views_fdb:get_update_seq(TxDb, Mrst),
-DataSize = get_total_view_size(TxDb, Mrst),
-JobStatus = case couch_views_jobs:job_state(TxDb, Mrst) of
+Mrst1 = couch_views_trees:open(TxDb, Mrst),
+Seq = couch_views_fdb:get_update_seq(TxDb, Mrst1),
+DataSize = get_total_view_size(TxDb, Mrst1),
+JobStatus = case couch_views_jobs:job_state(TxDb, Mrst1) of
 {ok, pending} -> true;
 {ok, running} -> true;
 {ok, finished} -> false;
@@ -124,10 +121,9 @@ get_info(Db, DDoc) ->
 
 
 get_total_view_size(TxDb, Mrst) ->
-ViewIds = [View#mrview.id_num || View <- Mrst#mrst.views],
-lists:foldl(fun (ViewId, Total) ->
-Total + couch_views_fdb:get_kv_size(TxDb, Mrst, ViewId)
-end, 0, ViewIds).
+lists:foldl(fun(View, Total) ->
+Total + couch_views_trees:get_kv_size(TxDb, View)
+end, 0, Mrst#mrst.views).
 
 
 read_view(Db, Mrst, ViewName, Callback, Acc0, Args) ->
@@ -185,16 +181,29 @@ to_mrargs(#{} = Args) ->
 end, #mrargs{}, Args).
 
 
-check_range(#mrargs{start_key = undefined}) ->
+check_range(Mrst, ViewName, Args) ->
+#mrst{
+language = Lang,
+views = Views
+} = Mrst,
+View = case couch_mrview_util:extract_view(Lang, Args, ViewName, Views) of
+{map, V, _} -> V;
+

[couchdb] 05/08: Use ebtree for reduce functions

2020-09-30 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/couchdb.git

commit 69f0ba1cc0af0c6008f63fb7342a60efa794634b
Author: Paul J. Davis 
AuthorDate: Wed Jul 29 10:34:48 2020 -0500

Use ebtree for reduce functions
---
 src/couch_views/src/couch_views.erl|   6 -
 src/couch_views/src/couch_views_fdb.erl|   1 -
 src/couch_views/src/couch_views_reader.erl | 159 ++-
 src/couch_views/src/couch_views_trees.erl  | 199 +
 4 files changed, 327 insertions(+), 38 deletions(-)

diff --git a/src/couch_views/src/couch_views.erl 
b/src/couch_views/src/couch_views.erl
index da8a142..2d91631 100644
--- a/src/couch_views/src/couch_views.erl
+++ b/src/couch_views/src/couch_views.erl
@@ -161,12 +161,6 @@ maybe_update_view(TxDb, Mrst, false, _Args) ->
 end.
 
 
-is_reduce_view(#mrargs{view_type = ViewType}) ->
-ViewType =:= red;
-is_reduce_view({Reduce, _, _}) ->
-Reduce =:= red.
-
-
 to_mrargs(#mrargs{} = Args) ->
 Args;
 
diff --git a/src/couch_views/src/couch_views_fdb.erl 
b/src/couch_views/src/couch_views_fdb.erl
index 28a60b8..b0fb82e 100644
--- a/src/couch_views/src/couch_views_fdb.erl
+++ b/src/couch_views/src/couch_views_fdb.erl
@@ -299,7 +299,6 @@ reset_interactive_index(Db, Sig, _St) ->
 {VS, ?INDEX_BUILDING}.
 
 
-
 version_key(Db, Sig) ->
 #{
 db_prefix := DbPrefix
diff --git a/src/couch_views/src/couch_views_reader.erl 
b/src/couch_views/src/couch_views_reader.erl
index a785c7b..3c58627 100644
--- a/src/couch_views/src/couch_views_reader.erl
+++ b/src/couch_views/src/couch_views_reader.erl
@@ -23,7 +23,15 @@
 -include_lib("fabric/include/fabric2.hrl").
 
 
-read(Db, Mrst0, ViewName, UserCallback, UserAcc0, Args) ->
+read(Db, Mrst, ViewName, UserCallback, UserAcc, Args) ->
+ReadFun = case Args of
+#mrargs{view_type = map} -> fun read_map_view/6;
+#mrargs{view_type = red} -> fun read_red_view/6
+end,
+ReadFun(Db, Mrst, ViewName, UserCallback, UserAcc, Args).
+
+
+read_map_view(Db, Mrst0, ViewName, UserCallback, UserAcc0, Args) ->
 try
 fabric2_fdb:transactional(Db, fun(TxDb) ->
 #mrst{
@@ -68,6 +76,79 @@ read(Db, Mrst0, ViewName, UserCallback, UserAcc0, Args) ->
 end.
 
 
+read_red_view(Db, Mrst0, ViewName, UserCallback, UserAcc0, Args) ->
+#mrst{
+language = Lang,
+views = Views
+} = Mrst0,
+{Idx, Lang, View0} = get_red_view(Lang, Args, ViewName, Views),
+Mrst1 = Mrst0#mrst{views = [View0]},
+ReadOpts = [{read_only, Idx}],
+try
+fabric2_fdb:transactional(Db, fun(TxDb) ->
+#mrst{
+language = Lang,
+views = [View1]
+} = Mrst = couch_views_trees:open(TxDb, Mrst1, ReadOpts),
+
+#mrargs{
+extra = Extra
+} = Args,
+
+Fun = fun handle_red_row/3,
+
+Meta = get_red_meta(TxDb, Mrst, View1, Args),
+UserAcc1 = maybe_stop(UserCallback(Meta, UserAcc0)),
+
+Finalizer = case couch_util:get_value(finalizer, Extra) of
+undefined ->
+{_, FunSrc} = lists:nth(Idx, View1#mrview.reduce_funs),
+FunSrc;
+CustomFun->
+CustomFun
+end,
+
+Acc0 = #{
+db => TxDb,
+skip => Args#mrargs.skip,
+limit => Args#mrargs.limit,
+mrargs => undefined,
+finalizer => Finalizer,
+red_idx => Idx,
+language => Lang,
+callback => UserCallback,
+acc => UserAcc1
+},
+
+Acc1 = lists:foldl(fun(KeyArgs, KeyAcc0) ->
+Opts = mrargs_to_fdb_options(KeyArgs),
+KeyAcc1 = KeyAcc0#{
+mrargs := KeyArgs
+},
+couch_views_trees:fold_red_idx(
+TxDb,
+View1,
+Idx,
+Opts,
+Fun,
+KeyAcc1
+)
+end, Acc0, expand_keys_args(Args)),
+
+#{
+acc := UserAcc2
+} = Acc1,
+{ok, maybe_stop(UserCallback(complete, UserAcc2))}
+end)
+catch
+throw:{complete, Out} ->
+{_, Final} = UserCallback(complete, Out),
+{ok, Final};
+throw:{done, Out} ->
+{ok, Out}
+end.
+
+
 get_map_meta(TxDb, Mrst, View, #mrargs{update_seq = true}) ->
 TotalRows = couch_views_trees:get_row_count(TxDb, View),
 ViewSeq = couch_views_fdb:get_update_seq(TxDb, Mrst),
@@ -78,6 +159,14 @@ get_map_meta(TxDb, _Mrst, View, #mrargs{}

[couchdb] 07/08: Add elixir tests for builtin reduce group levels

2020-09-30 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/couchdb.git

commit 811741d9b6dce3403b0330d9bdb860518764e1a9
Author: Garren Smith 
AuthorDate: Thu Sep 24 12:10:29 2020 -0500

Add elixir tests for builtin reduce group levels
---
 .../test/reduce_builtin_group_level_tests.exs  | 549 +
 1 file changed, 549 insertions(+)

diff --git a/test/elixir/test/reduce_builtin_group_level_tests.exs 
b/test/elixir/test/reduce_builtin_group_level_tests.exs
new file mode 100644
index 000..2a18349
--- /dev/null
+++ b/test/elixir/test/reduce_builtin_group_level_tests.exs
@@ -0,0 +1,549 @@
+defmodule ReduceBuiltinGroupLevelTests do
+  use CouchTestCase
+
+  setup do
+db_name = random_db_name()
+{:ok, _} = create_db(db_name)
+on_exit(fn -> delete_db(db_name) end)
+
+docs = create_docs()
+ddoc = create_ddoc()
+
+body = %{
+  docs: [ddoc | docs]
+}
+
+resp = Couch.post("/#{db_name}/_bulk_docs", body: body)
+Enum.each(resp.body, (&1["ok"]))
+
+%{
+  :db_name => db_name,
+  :ddoc => ddoc
+}
+  end
+
+  test "group_level=0 reduce startkey/endkey", context do
+args = %{
+  reduce: true,
+  group_level: 0,
+  start_key: [2018, 3, 2],
+  end_key: [2019, 5, 1]
+}
+
+correct = [
+  %{"key" => :null, "value" => 31}
+]
+
+run_query(context, args, "dates_sum", correct)
+  end
+
+  test "group_level=0 reduce", context do
+args = %{
+  reduce: true,
+  group_level: 0
+}
+
+correct = [
+  %{"key" => :null, "value" => 68}
+]
+
+run_query(context, args, "dates_sum", correct)
+  end
+
+  test "group_level=1 reduce", context do
+args = %{
+  reduce: true,
+  group_level: 1
+}
+
+correct = [
+  %{"key" => [2017], "value" => 31},
+  %{"key" => [2018], "value" => 20},
+  %{"key" => [2019], "value" => 17}
+]
+
+run_query(context, args, "dates_sum", correct)
+  end
+
+  test "group_level=1 reduce with startkey/endkey", context do
+args = %{
+  reduce: true,
+  group_level: 1,
+  start_key: [2017, 4, 1],
+  end_key: [2018, 3, 1]
+}
+
+correct = [
+  %{"key" => [2017], "value" => 22},
+  %{"key" => [2018], "value" => 6}
+]
+
+run_query(context, args, "dates_sum", correct)
+  end
+
+  test "group_level=1 reduce with startkey/endkey take 2", context do
+args = %{
+  reduce: true,
+  group_level: 1,
+  start_key: [2017, 4, 1],
+  end_key: [2019, 3, 2]
+}
+
+correct = [
+  %{"key" => [2017], "value" => 22},
+  %{"key" => [2018], "value" => 20},
+  %{"key" => [2019], "value" => 4}
+]
+
+run_query(context, args, "dates_sum", correct)
+  end
+
+  test "group_level=1 reduce with startkey/endkey take 3", context do
+args = %{
+  reduce: true,
+  group_level: 1,
+  start_key: [2017, 4, 1],
+  end_key: [2019, 05, 1]
+}
+
+correct = [
+  %{"key" => [2017], "value" => 22},
+  %{"key" => [2018], "value" => 20},
+  %{"key" => [2019], "value" => 17}
+]
+
+run_query(context, args, "dates_sum", correct)
+  end
+
+  test "group_level=1 reduce with startkey", context do
+args = %{
+  reduce: true,
+  group_level: 1,
+  start_key: [2017, 4, 1]
+}
+
+correct = [
+  %{"key" => [2017], "value" => 22},
+  %{"key" => [2018], "value" => 20},
+  %{"key" => [2019], "value" => 17}
+]
+
+run_query(context, args, "dates_sum", correct)
+  end
+
+  test "group_level=1 reduce with endkey", context do
+args = %{
+  reduce: true,
+  group_level: 1,
+  end_key: [2018, 5, 2]
+}
+
+correct = [
+  %{"key" => [2017], "value" => 31},
+  %{"key" => [2018], "value" => 20}
+]
+
+run_query(context, args, "dates_sum", correct)
+  end
+
+  test "group=true reduce with startkey/endkey", context do
+args = %{
+  reduce: true,
+  group: true,
+  start_key: [2018, 5, 1],
+  end_key: [2019, 04, 1]
+}
+
+correct = [
+  %{"key" => [2018, 5, 1], "value" => 7},
+  %{"key" => [2019, 3, 1], "value" => 4},
+  %{"key" => [20

[couchdb] branch main updated (f190677 -> 4a4515e)

2020-09-30 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a change to branch main
in repository https://gitbox.apache.org/repos/asf/couchdb.git.


from f190677  Workaround dirty schedulers in run_queue stats (#3168)
 new ddae72a  Export fabric2_fdb:chunkify_binary/1,2
 new b91f193  Views on ebtree
 new a8cebfa  Reimplement db wide view size tracking
 new ef6b60b  Upgrade legacy views
 new 69f0ba1  Use ebtree for reduce functions
 new 2f1a456  Add test suite for reduce views
 new 811741d  Add elixir tests for builtin reduce group levels
 new 4a4515e  Optimizations for reading reduce views

The 8 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:
 rel/overlay/etc/default.ini|   6 +
 src/couch/src/couch_query_servers.erl  |   7 +-
 src/couch_views/include/couch_views.hrl|   9 +
 src/couch_views/src/couch_views.erl|  61 +-
 src/couch_views/src/couch_views_fdb.erl| 508 +
 src/couch_views/src/couch_views_indexer.erl|  60 +-
 src/couch_views/src/couch_views_reader.erl | 254 +--
 src/couch_views/src/couch_views_trees.erl  | 587 +++
 src/couch_views/src/couch_views_updater.erl|  13 +-
 src/couch_views/src/couch_views_util.erl   |  35 +
 src/couch_views/test/couch_views_cleanup_test.erl  |   2 +-
 src/couch_views/test/couch_views_indexer_test.erl  |  64 +-
 src/couch_views/test/couch_views_red_test.erl  | 745 +++
 src/couch_views/test/couch_views_size_test.erl | 824 -
 src/couch_views/test/couch_views_updater_test.erl  |   4 +-
 src/couch_views/test/couch_views_upgrade_test.erl  | 400 ++
 src/fabric/src/fabric2_fdb.erl |  33 +-
 src/mango/src/mango_cursor_view.erl|  14 +-
 src/mango/src/mango_idx_view.erl   |   7 +-
 src/mango/src/{mango.hrl => mango_idx_view.hrl}|   2 +-
 .../test/reduce_builtin_group_level_tests.exs  | 549 ++
 21 files changed, 3151 insertions(+), 1033 deletions(-)
 create mode 100644 src/couch_views/src/couch_views_trees.erl
 create mode 100644 src/couch_views/test/couch_views_red_test.erl
 create mode 100644 src/couch_views/test/couch_views_upgrade_test.erl
 copy src/mango/src/{mango.hrl => mango_idx_view.hrl} (90%)
 create mode 100644 test/elixir/test/reduce_builtin_group_level_tests.exs



[couchdb] 04/08: Upgrade legacy views

2020-09-30 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/couchdb.git

commit ef6b60b760a79542df31df9c7ad64d737b860c92
Author: Paul J. Davis 
AuthorDate: Fri Sep 18 11:05:00 2020 -0500

Upgrade legacy views
---
 src/couch_views/include/couch_views.hrl   |   4 +
 src/couch_views/src/couch_views_fdb.erl   | 180 --
 src/couch_views/src/couch_views_indexer.erl   |   8 +-
 src/couch_views/test/couch_views_upgrade_test.erl | 400 ++
 4 files changed, 551 insertions(+), 41 deletions(-)

diff --git a/src/couch_views/include/couch_views.hrl 
b/src/couch_views/include/couch_views.hrl
index 3882191..92b8f46 100644
--- a/src/couch_views/include/couch_views.hrl
+++ b/src/couch_views/include/couch_views.hrl
@@ -10,6 +10,9 @@
 % License for the specific language governing permissions and limitations under
 % the License.
 
+% Current implementation version
+-define(CURRENT_VIEW_IMPL_VERSION, 1).
+
 % Index info/data subspaces
 -define(VIEW_INFO, 0).
 -define(VIEW_DATA, 1).
@@ -21,6 +24,7 @@
 -define(VIEW_KV_SIZE, 2).
 -define(VIEW_BUILD_STATUS, 3).
 -define(VIEW_CREATION_VS, 4).
+-define(VIEW_IMPL_VERSION, 5).
 
 % Data keys
 -define(VIEW_ID_RANGE, 0).
diff --git a/src/couch_views/src/couch_views_fdb.erl 
b/src/couch_views/src/couch_views_fdb.erl
index f238a8f..28a60b8 100644
--- a/src/couch_views/src/couch_views_fdb.erl
+++ b/src/couch_views/src/couch_views_fdb.erl
@@ -13,6 +13,8 @@
 -module(couch_views_fdb).
 
 -export([
+get_view_state/2,
+
 new_interactive_index/3,
 new_creation_vs/3,
 get_creation_vs/2,
@@ -40,52 +42,89 @@
 -include_lib("fabric/include/fabric2.hrl").
 
 
-new_interactive_index(Db, Mrst, VS) ->
-couch_views_fdb:new_creation_vs(Db, Mrst, VS),
-couch_views_fdb:set_build_status(Db, Mrst, ?INDEX_BUILDING).
+get_view_state(Db, #mrst{} = Mrst) ->
+get_view_state(Db, Mrst#mrst.sig);
+
+get_view_state(Db, Sig) when is_binary(Sig) ->
+#{
+tx := Tx
+} = Db,
+
+VersionF = erlfdb:get(Tx, version_key(Db, Sig)),
+ViewSeqF = erlfdb:get(Tx, seq_key(Db, Sig)),
+ViewVSF = erlfdb:get(Tx, creation_vs_key(Db, Sig)),
+BuildStatusF = erlfdb:get(Tx, build_status_key(Db, Sig)),
+
+Version = case erlfdb:wait(VersionF) of
+not_found -> not_found;
+VsnVal -> element(1, erlfdb_tuple:unpack(VsnVal))
+end,
+
+ViewSeq = case erlfdb:wait(ViewSeqF) of
+not_found -> <<>>;
+SeqVal -> SeqVal
+end,
+
+ViewVS = case erlfdb:wait(ViewVSF) of
+not_found -> not_found;
+VSVal -> element(1, erlfdb_tuple:unpack(VSVal))
+end,
+
+State = #{
+version => Version,
+view_seq => ViewSeq,
+view_vs => ViewVS,
+build_status => erlfdb:wait(BuildStatusF)
+},
+
+maybe_upgrade_view(Db, Sig, State).
+
+
+new_interactive_index(Db, #mrst{} = Mrst, VS) ->
+new_interactive_index(Db, Mrst#mrst.sig, VS);
+
+new_interactive_index(Db, Sig, VS) ->
+set_version(Db, Sig),
+new_creation_vs(Db, Sig, VS),
+set_build_status(Db, Sig, ?INDEX_BUILDING).
 
 
 %Interactive View Creation Versionstamp
 %(, ?DB_VIEWS, ?VIEW_INFO, ?VIEW_CREATION_VS, Sig) = VS
 
 new_creation_vs(TxDb, #mrst{} = Mrst, VS) ->
+new_creation_vs(TxDb, Mrst#mrst.sig, VS);
+
+new_creation_vs(TxDb, Sig, VS) ->
 #{
 tx := Tx
 } = TxDb,
-Key = creation_vs_key(TxDb, Mrst#mrst.sig),
+Key = creation_vs_key(TxDb, Sig),
 Value = erlfdb_tuple:pack_vs({VS}),
 ok = erlfdb:set_versionstamped_value(Tx, Key, Value).
 
 
-get_creation_vs(TxDb, #mrst{} = Mrst) ->
-get_creation_vs(TxDb, Mrst#mrst.sig);
-
-get_creation_vs(TxDb, Sig) ->
+get_creation_vs(TxDb, MrstOrSig) ->
 #{
-tx := Tx
-} = TxDb,
-Key = creation_vs_key(TxDb, Sig),
-case erlfdb:wait(erlfdb:get(Tx, Key)) of
-not_found ->
-not_found;
-EK ->
-{VS} = erlfdb_tuple:unpack(EK),
-VS
-end.
+view_vs := ViewVS
+} = get_view_state(TxDb, MrstOrSig),
+ViewVS.
 
 
 %Interactive View Build Status
 %(, ?DB_VIEWS, ?VIEW_INFO, ?VIEW_BUILD_STATUS, Sig) = INDEX_BUILDING | 
INDEX_READY
 
-get_build_status(TxDb, #mrst{sig = Sig}) ->
+get_build_status(TxDb, MrstOrSig) ->
 #{
-tx := Tx
-} = TxDb,
-Key = build_status_key(TxDb, Sig),
-erlfdb:wait(erlfdb:get(Tx, Key)).
+build_status := BuildStatus
+} = get_view_state(TxDb, MrstOrSig),
+BuildStatus.
 
 
-set_build_status(TxDb, #mrst{sig = Sig}, State) ->
+set_build_status(TxDb, #mrst{} = Mrst, State) ->
+set_build_status(TxDb, Mrst#mrst.sig, State);
+
+set_build_status(TxDb, Sig, State) ->
 #{
 tx := Tx
 } = TxDb,
@@ -98,24 +137,18 @@ set_build_status(TxDb, #mrst{sig = Sig}, State) ->
 % (, ?DB_VI

[couchdb] 01/08: Export fabric2_fdb:chunkify_binary/1,2

2020-09-30 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/couchdb.git

commit ddae72a707ce51c229da9188275f18664302cba7
Author: Paul J. Davis 
AuthorDate: Thu Aug 6 12:34:29 2020 -0500

Export fabric2_fdb:chunkify_binary/1,2
---
 src/fabric/src/fabric2_fdb.erl | 33 ++---
 1 file changed, 18 insertions(+), 15 deletions(-)

diff --git a/src/fabric/src/fabric2_fdb.erl b/src/fabric/src/fabric2_fdb.erl
index 52303ce..36fa451 100644
--- a/src/fabric/src/fabric2_fdb.erl
+++ b/src/fabric/src/fabric2_fdb.erl
@@ -77,6 +77,9 @@
 
 get_approximate_tx_size/1,
 
+chunkify_binary/1,
+chunkify_binary/2,
+
 debug_cluster/0,
 debug_cluster/2
 ]).
@@ -1176,6 +1179,21 @@ get_approximate_tx_size(#{} = TxDb) ->
 erlfdb:wait(erlfdb:get_approximate_size(Tx)).
 
 
+chunkify_binary(Data) ->
+chunkify_binary(Data, binary_chunk_size()).
+
+
+chunkify_binary(Data, Size) ->
+case Data of
+<<>> ->
+[];
+<> ->
+[Head | chunkify_binary(Rest, Size)];
+<<_/binary>> when size(Data) < Size ->
+[Data]
+end.
+
+
 debug_cluster() ->
 debug_cluster(<<>>, <<16#FE, 16#FF, 16#FF>>).
 
@@ -1677,21 +1695,6 @@ sum_rem_rev_sizes(RevInfos) ->
 end, 0, RevInfos).
 
 
-chunkify_binary(Data) ->
-chunkify_data(Data, binary_chunk_size()).
-
-
-chunkify_data(Data, Size) ->
-case Data of
-<<>> ->
-[];
-<> ->
-[Head | chunkify_data(Rest, Size)];
-<<_/binary>> when size(Data) < Size ->
-[Data]
-end.
-
-
 get_fold_acc(Db, RangePrefix, UserCallback, UserAcc, Options)
 when is_map(Db) orelse Db =:= undefined ->
 



[couchdb] 08/08: Optimizations for reading reduce views

2020-09-30 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/couchdb.git

commit 4a4515e01d82a6f88ecd3a6b61b5beeab6127424
Author: Paul J. Davis 
AuthorDate: Tue Sep 29 15:23:32 2020 -0500

Optimizations for reading reduce views

These are a few micro optimizations to avoid unnecessary work when
reading from a single reduce function during a view read.
---
 src/couch/src/couch_query_servers.erl | 7 ++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/src/couch/src/couch_query_servers.erl 
b/src/couch/src/couch_query_servers.erl
index 447daea..8eb07ab 100644
--- a/src/couch/src/couch_query_servers.erl
+++ b/src/couch/src/couch_query_servers.erl
@@ -111,6 +111,8 @@ rereduce(Lang, RedSrcs, ReducedValues) ->
 
 reduce(_Lang, [], _KVs) ->
 {ok, []};
+reduce(Lang, [<<"_", _/binary>>] = RedSrcs, KVs) ->
+builtin_reduce(reduce, RedSrcs, KVs, []);
 reduce(Lang, RedSrcs, KVs) ->
 {OsRedSrcs, BuiltinReds} = lists:partition(fun
 (<<"_", _/binary>>) -> false;
@@ -171,7 +173,10 @@ builtin_reduce(_Re, [], _KVs, Acc) ->
 {ok, lists:reverse(Acc)};
 builtin_reduce(Re, [<<"_sum",_/binary>>|BuiltinReds], KVs, Acc) ->
 Sum = builtin_sum_rows(KVs, 0),
-Red = check_sum_overflow(?term_size(KVs), ?term_size(Sum), Sum),
+Red = case is_number(Sum) of
+true -> Sum;
+false -> check_sum_overflow(?term_size(KVs), ?term_size(Sum), Sum)
+end,
 builtin_reduce(Re, BuiltinReds, KVs, [Red|Acc]);
 builtin_reduce(reduce, [<<"_count",_/binary>>|BuiltinReds], KVs, Acc) ->
 Count = length(KVs),



[couchdb] 06/08: Add test suite for reduce views

2020-09-30 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/couchdb.git

commit 2f1a4562e98a423d3d93dab06682bd1be9b39435
Author: Paul J. Davis 
AuthorDate: Wed Aug 5 12:47:37 2020 -0500

Add test suite for reduce views
---
 src/couch_views/test/couch_views_red_test.erl | 745 ++
 1 file changed, 745 insertions(+)

diff --git a/src/couch_views/test/couch_views_red_test.erl 
b/src/couch_views/test/couch_views_red_test.erl
new file mode 100644
index 000..707611f
--- /dev/null
+++ b/src/couch_views/test/couch_views_red_test.erl
@@ -0,0 +1,745 @@
+% 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(couch_views_red_test).
+
+-include_lib("couch/include/couch_eunit.hrl").
+-include_lib("couch/include/couch_db.hrl").
+-include_lib("fabric/test/fabric2_test.hrl").
+-include("couch_views.hrl").
+
+
+-define(NUM_DOCS, 2000).
+
+
+reduce_views_shraed_db_test_() ->
+{
+"Reduce views",
+{
+setup,
+fun setup_db_with_docs/0,
+fun teardown_db/1,
+with([
+?TDEF(should_reduce),
+?TDEF(should_reduce_rev),
+?TDEF(should_reduce_start_key),
+?TDEF(should_reduce_start_key_rev),
+?TDEF(should_reduce_end_key),
+?TDEF(should_reduce_end_key_rev),
+?TDEF(should_reduce_inclusive_end_false),
+?TDEF(should_reduce_inclusive_end_false_rev),
+?TDEF(should_reduce_start_and_end_key),
+?TDEF(should_reduce_start_and_end_key_rev),
+?TDEF(should_reduce_empty_range),
+?TDEF(should_reduce_empty_range_rev),
+?TDEF(should_reduce_grouped),
+?TDEF(should_reduce_grouped_rev),
+?TDEF(should_reduce_grouped_start_key),
+?TDEF(should_reduce_grouped_start_key_rev),
+?TDEF(should_reduce_grouped_end_key),
+?TDEF(should_reduce_grouped_end_key_rev),
+?TDEF(should_reduce_grouped_inclusive_end_false),
+?TDEF(should_reduce_grouped_inclusive_end_false_rev),
+?TDEF(should_reduce_grouped_start_and_end_key),
+?TDEF(should_reduce_grouped_start_and_end_key_rev),
+?TDEF(should_reduce_grouped_empty_range),
+?TDEF(should_reduce_grouped_empty_range_rev),
+?TDEF(should_reduce_array_keys),
+?TDEF(should_reduce_grouped_array_keys),
+?TDEF(should_reduce_group_1_array_keys),
+?TDEF(should_reduce_group_1_array_keys_start_key),
+?TDEF(should_reduce_group_1_array_keys_start_key_rev),
+?TDEF(should_reduce_group_1_array_keys_end_key),
+?TDEF(should_reduce_group_1_array_keys_end_key_rev),
+?TDEF(should_reduce_group_1_array_keys_inclusive_end_false),
+
?TDEF(should_reduce_group_1_array_keys_inclusive_end_false_rev),
+?TDEF(should_reduce_group_1_array_keys_start_and_end_key),
+?TDEF(should_reduce_group_1_array_keys_start_and_end_key_rev),
+?TDEF(should_reduce_group_1_array_keys_sub_array_select),
+?TDEF(should_reduce_group_1_array_keys_sub_array_select_rev),
+
?TDEF(should_reduce_group_1_array_keys_sub_array_inclusive_end),
+?TDEF(should_reduce_group_1_array_keys_empty_range),
+?TDEF(should_reduce_group_1_array_keys_empty_range_rev)
+])
+}
+}.
+
+
+reduce_views_collation_test_() ->
+{
+"Reduce collation test",
+{
+setup,
+fun setup_db/0,
+fun teardown_db/1,
+with([
+?TDEF(should_collate_group_keys)
+])
+}
+}.
+
+
+setup_db() ->
+Ctx = test_util:start_couch([
+fabric,
+couch_jobs,
+couch_js,
+couch_views
+]),
+{ok, Db} = fabric2_db:create(?tempdb(), [{user_ctx, ?ADMIN_USER}]),
+{Db, Ctx}.
+
+
+setup_db_with_docs() ->
+{Db, Ctx} = setup_db(),
+fabric2_db:update_docs(Db, [create_ddoc()]),
+make_docs(Db, ?NUM_DOCS),
+run_query(Db, <<"baz">>, #{l

[couchdb] 01/01: Use JSON collation

2020-09-29 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a commit to branch fdb-btree-reduce-davisp
in repository https://gitbox.apache.org/repos/asf/couchdb.git

commit ecb067ba1a2b32a1d6a5a210d496664adedd55ce
Author: Paul J. Davis 
AuthorDate: Tue Sep 29 09:56:19 2020 -0500

Use JSON collation
---
 src/couch_views/src/couch_views_reduce_fdb.erl | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/src/couch_views/src/couch_views_reduce_fdb.erl 
b/src/couch_views/src/couch_views_reduce_fdb.erl
index a5cb905..8ea2061 100644
--- a/src/couch_views/src/couch_views_reduce_fdb.erl
+++ b/src/couch_views/src/couch_views_reduce_fdb.erl
@@ -193,11 +193,18 @@ open_tree(TxDb, Sig, ViewId, ViewReduceFun) ->
 
 TreeOpts = [
 {reduce_fun, get_reducer(ViewReduceFun)},
+{collate_fun, fun less_json_rows/2},
 {encode_fun, EncodeFun}
 ],
 ebtree:open(Tx, ReduceIdxPrefix, btree_order_size(), TreeOpts).
 
 
+less_json_rows({_, _} = A, {_, _} = B) ->
+couch_ejson_compare:less_json_ids(A, B);
+less_json_rows(A, B) ->
+couch_ejson_compare:less_json(A, B).
+
+
 delete_keys(Tx, Tree, DocId, Keys) ->
 lists:foreach(fun (Key) ->
 EK = create_key(Key, DocId),



[couchdb] branch fdb-btree-reduce-davisp created (now ecb067b)

2020-09-29 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a change to branch fdb-btree-reduce-davisp
in repository https://gitbox.apache.org/repos/asf/couchdb.git.


  at ecb067b  Use JSON collation

This branch includes the following new commits:

 new ecb067b  Use JSON collation

The 1 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.




[couchdb] branch feature-ebtree-views updated (fc5b4cf -> a57d73b)

2020-09-29 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a change to branch feature-ebtree-views
in repository https://gitbox.apache.org/repos/asf/couchdb.git.


 discard fc5b4cf  Add elixir tests for builtin reduce group levels
 discard 91c0e20  Add test suite for reduce views
 discard 4029451  Use ebtree for reduce functions
 add 99d9951  Use ebtree for reduce functions
 add 234a295  Add test suite for reduce views
 add 1460d4f  Add elixir tests for builtin reduce group levels
 add a57d73b  Optimizations for reading reduce views

This update added new revisions after undoing existing revisions.
That is to say, some revisions that were in the old version of the
branch are not in the new version.  This situation occurs
when a user --force pushes a change and generates a repository
containing something like this:

 * -- * -- B -- O -- O -- O   (fc5b4cf)
\
 N -- N -- N   refs/heads/feature-ebtree-views (a57d73b)

You should already have received notification emails for all of the O
revisions, and so the following emails describe only the N revisions
from the common base, B.

Any revisions marked "omit" are not gone; other references still
refer to them.  Any revisions marked "discard" are gone forever.

No new revisions were added by this update.

Summary of changes:
 src/couch/src/couch_query_servers.erl  |  7 +++-
 src/couch_views/src/couch_views_reader.erl | 18 ++
 src/couch_views/src/couch_views_trees.erl  | 55 ++
 3 files changed, 67 insertions(+), 13 deletions(-)



[couchdb] branch feature-ebtree-views updated (e079a87 -> fc5b4cf)

2020-09-24 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a change to branch feature-ebtree-views
in repository https://gitbox.apache.org/repos/asf/couchdb.git.


omit e079a87  Add elixir tests for builtin reduce group levels
omit cb28503  Add test suite for reduce views
omit 54e9bcf  Use ebtree for reduce functions
omit d035d8d  Upgrade legacy views
omit bd9486b  Reimplement db wide view size tracking
omit 4e32f82  Views on ebtree
omit 3b508e0  Export fabric2_fdb:chunkify_binary/1,2
omit fa3c3c8  Calculate external JSON size of a view row
 add aa21588  Export fabric2_fdb:chunkify_binary/1,2
 add 40238da  Views on ebtree
 add f47c066  Reimplement db wide view size tracking
 add 1f83890  Upgrade legacy views
 add 4029451  Use ebtree for reduce functions
 add 91c0e20  Add test suite for reduce views
 add fc5b4cf  Add elixir tests for builtin reduce group levels

This update added new revisions after undoing existing revisions.
That is to say, some revisions that were in the old version of the
branch are not in the new version.  This situation occurs
when a user --force pushes a change and generates a repository
containing something like this:

 * -- * -- B -- O -- O -- O   (e079a87)
\
 N -- N -- N   refs/heads/feature-ebtree-views (fc5b4cf)

You should already have received notification emails for all of the O
revisions, and so the following emails describe only the N revisions
from the common base, B.

Any revisions marked "omit" are not gone; other references still
refer to them.  Any revisions marked "discard" are gone forever.

No new revisions were added by this update.

Summary of changes:
 src/couch/src/couch_ejson_size.erl |  5 ---
 src/couch_views/src/couch_views_trees.erl  |  2 +-
 src/couch_views/test/couch_views_size_test.erl | 60 +-
 3 files changed, 31 insertions(+), 36 deletions(-)



[couchdb] branch re-enable-most-elixir-tests created (now 2e763ae)

2020-09-24 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a change to branch re-enable-most-elixir-tests
in repository https://gitbox.apache.org/repos/asf/couchdb.git.


  at 2e763ae  Re-enable most elixir tests

This branch includes the following new commits:

 new 7e861d8  Remove quorum tests
 new 2e763ae  Re-enable most elixir tests

The 2 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.




[couchdb] 01/02: Remove quorum tests

2020-09-24 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a commit to branch re-enable-most-elixir-tests
in repository https://gitbox.apache.org/repos/asf/couchdb.git

commit 7e861d87fa9af46d153bb5233f66799b55291edf
Author: Paul J. Davis 
AuthorDate: Thu Sep 24 13:36:10 2020 -0500

Remove quorum tests

Quorum is no longer a thing now that we rely on FoundationDB.
---
 Makefile   |  18 +-
 Makefile.win   |  16 +-
 test/elixir/test/cluster_with_quorum_test.exs  | 186 -
 test/elixir/test/cluster_without_quorum_test.exs   | 185 
 .../tests-cluster/with-quorum/attachments.js   |  37 
 .../with-quorum/attachments_delete.js  |  33 
 .../attachments_delete_overridden_quorum.js|  38 -
 .../with-quorum/attachments_overridden_quorum.js   |  42 -
 .../tests-cluster/with-quorum/db_creation.js   |  28 
 .../with-quorum/db_creation_overridden_quorum.js   |  30 
 .../tests-cluster/with-quorum/db_deletion.js   |  31 
 .../with-quorum/db_deletion_overridden_quorum.js   |  24 ---
 .../tests-cluster/with-quorum/doc_bulk.js  |  26 ---
 .../with-quorum/doc_bulk_overridden_quorum.js  |  26 ---
 .../tests-cluster/with-quorum/doc_copy.js  |  28 
 .../with-quorum/doc_copy_overridden_quorum.js  |  32 
 .../tests-cluster/with-quorum/doc_crud.js  |  32 
 .../with-quorum/doc_crud_overridden_quorum.js  |  32 
 .../tests-cluster/without-quorum/attachments.js|  40 -
 .../without-quorum/attachments_delete.js   |  39 -
 .../attachments_delete_overridden_quorum.js|  38 -
 .../attachments_overridden_quorum.js   |  43 -
 .../tests-cluster/without-quorum/db_creation.js|  28 
 .../db_creation_overridden_quorum.js   |  32 
 .../tests-cluster/without-quorum/db_deletion.js|  31 
 .../db_deletion_overridden_quorum.js   |  26 ---
 .../tests-cluster/without-quorum/doc_bulk.js   |  29 
 .../without-quorum/doc_bulk_overridden_quorum.js   |  29 
 .../tests-cluster/without-quorum/doc_copy.js   |  31 
 .../without-quorum/doc_copy_overridden_quorum.js   |  35 
 .../tests-cluster/without-quorum/doc_crud.js   |  36 
 .../without-quorum/doc_crud_overridden_quorum.js   |  35 
 32 files changed, 3 insertions(+), 1313 deletions(-)

diff --git a/Makefile b/Makefile
index 5bef9c7..b1d9d71 100644
--- a/Makefile
+++ b/Makefile
@@ -244,7 +244,7 @@ elixir: elixir-init elixir-check-formatted elixir-credo 
devclean
--enable-erlang-views \
--locald-config test/elixir/test/config/test-config.ini \
--erlang-config rel/files/eunit.config \
-   --no-eval 'mix test --trace --exclude without_quorum_test 
--exclude with_quorum_test $(EXUNIT_OPTS)'
+   --no-eval 'mix test --trace $(EXUNIT_OPTS)'
 
 .PHONY: elixir-only
 elixir-only: devclean
@@ -254,27 +254,13 @@ elixir-only: devclean
--enable-erlang-views \
--locald-config test/elixir/test/config/test-config.ini \
--erlang-config rel/files/eunit.config \
-   --no-eval 'mix test --trace --exclude without_quorum_test 
--exclude with_quorum_test $(EXUNIT_OPTS)'
+   --no-eval 'mix test --trace $(EXUNIT_OPTS)'
 
 .PHONY: elixir-init
 elixir-init: MIX_ENV=test
 elixir-init: config.erl
@mix local.rebar --force && mix local.hex --force && mix deps.get
 
-.PHONY: elixir-cluster-without-quorum
-elixir-cluster-without-quorum: export MIX_ENV=integration
-elixir-cluster-without-quorum: elixir-init elixir-check-formatted elixir-credo 
devclean
-   @dev/run -n 3 -q -a adm:pass \
-   --degrade-cluster 2 \
-   --no-eval 'mix test --trace --only without_quorum_test 
$(EXUNIT_OPTS)'
-
-.PHONY: elixir-cluster-with-quorum
-elixir-cluster-with-quorum: export MIX_ENV=integration
-elixir-cluster-with-quorum: elixir-init elixir-check-formatted elixir-credo 
devclean
-   @dev/run -n 3 -q -a adm:pass \
-   --degrade-cluster 1 \
-   --no-eval 'mix test --trace --only with_quorum_test 
$(EXUNIT_OPTS)'
-
 .PHONY: elixir-check-formatted
 elixir-check-formatted: elixir-init
@mix format --check-formatted
diff --git a/Makefile.win b/Makefile.win
index edfc1bf..6b254e2 100644
--- a/Makefile.win
+++ b/Makefile.win
@@ -207,27 +207,13 @@ elixir: export COUCHDB_TEST_ADMIN_PARTY_OVERRIDE=1
 elixir: elixir-init elixir-check-formatted elixir-credo devclean
@dev\run $(TEST_OPTS) -a adm:pass -n 1 --enable-erlang-views \
   --locald-config test/elixir/test/config/test-config.ini \
-  --no-eval 'mix test --trace --exclude without_quorum_test --exclude 
with_quorum_test $(EXUNIT_OPTS)'
+  --no-eval 'mix test --trace $(EXUNIT_OPTS)'
 
 .PH

[couchdb] 02/02: Re-enable most elixir tests

2020-09-24 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a commit to branch re-enable-most-elixir-tests
in repository https://gitbox.apache.org/repos/asf/couchdb.git

commit 2e763aea3dcdede5e69cac1a4aa8d3859b6159ed
Author: Paul J. Davis 
AuthorDate: Thu Sep 24 15:06:13 2020 -0500

Re-enable most elixir tests

This change tags all tests that are currently failing against main with
a `pending` tag that is then excluded.
---
 Makefile   | 4 ++--
 Makefile.win   | 2 +-
 test/elixir/test/attachments_multipart_test.exs| 1 +
 test/elixir/test/attachments_test.exs  | 2 ++
 test/elixir/test/changes_async_test.exs| 9 +
 test/elixir/test/changes_test.exs  | 1 +
 test/elixir/test/coffee_test.exs   | 1 +
 test/elixir/test/config_test.exs   | 1 +
 test/elixir/test/cookie_auth_test.exs  | 1 +
 test/elixir/test/design_docs_test.exs  | 4 
 test/elixir/test/design_options_test.exs   | 1 +
 test/elixir/test/design_paths_test.exs | 3 +++
 test/elixir/test/erlang_views_test.exs | 3 +++
 test/elixir/test/http_test.exs | 2 ++
 test/elixir/test/proxyauth_test.exs| 2 ++
 test/elixir/test/purge_test.exs| 2 ++
 test/elixir/test/reader_acl_test.exs   | 5 +
 test/elixir/test/replicator_db_bad_rep_id_test.exs | 1 +
 test/elixir/test/replicator_db_by_doc_id_test.exs  | 1 +
 test/elixir/test/rev_stemming_test.exs | 1 +
 test/elixir/test/rewrite_test.exs  | 1 +
 test/elixir/test/update_documents_test.exs | 9 +
 test/elixir/test/users_db_test.exs | 1 +
 test/elixir/test/view_compaction_test.exs  | 5 +++--
 test/elixir/test/view_errors_test.exs  | 3 +++
 test/elixir/test/view_include_docs_test.exs| 1 +
 test/elixir/test/view_offsets_test.exs | 2 ++
 test/elixir/test/view_pagination_test.exs  | 6 ++
 test/elixir/test/view_update_seq_test.exs  | 3 +++
 29 files changed, 73 insertions(+), 5 deletions(-)

diff --git a/Makefile b/Makefile
index b1d9d71..714b9b1 100644
--- a/Makefile
+++ b/Makefile
@@ -244,7 +244,7 @@ elixir: elixir-init elixir-check-formatted elixir-credo 
devclean
--enable-erlang-views \
--locald-config test/elixir/test/config/test-config.ini \
--erlang-config rel/files/eunit.config \
-   --no-eval 'mix test --trace $(EXUNIT_OPTS)'
+   --no-eval 'mix test --trace --exclude pending $(EXUNIT_OPTS)'
 
 .PHONY: elixir-only
 elixir-only: devclean
@@ -254,7 +254,7 @@ elixir-only: devclean
--enable-erlang-views \
--locald-config test/elixir/test/config/test-config.ini \
--erlang-config rel/files/eunit.config \
-   --no-eval 'mix test --trace $(EXUNIT_OPTS)'
+   --no-eval 'mix test --trace --exclude pending $(EXUNIT_OPTS)'
 
 .PHONY: elixir-init
 elixir-init: MIX_ENV=test
diff --git a/Makefile.win b/Makefile.win
index 6b254e2..84a933c 100644
--- a/Makefile.win
+++ b/Makefile.win
@@ -207,7 +207,7 @@ elixir: export COUCHDB_TEST_ADMIN_PARTY_OVERRIDE=1
 elixir: elixir-init elixir-check-formatted elixir-credo devclean
@dev\run $(TEST_OPTS) -a adm:pass -n 1 --enable-erlang-views \
   --locald-config test/elixir/test/config/test-config.ini \
-  --no-eval 'mix test --trace $(EXUNIT_OPTS)'
+  --no-eval 'mix test --trace --exclude pending $(EXUNIT_OPTS)'
 
 .PHONY: elixir-init
 elixir-init: MIX_ENV=test
diff --git a/test/elixir/test/attachments_multipart_test.exs 
b/test/elixir/test/attachments_multipart_test.exs
index f635377..5f387cf 100644
--- a/test/elixir/test/attachments_multipart_test.exs
+++ b/test/elixir/test/attachments_multipart_test.exs
@@ -9,6 +9,7 @@ defmodule AttachmentMultipartTest do
   This is a port of the attachments_multipart.js suite
   """
 
+  @tag :pending # HTTP 500
   @tag :with_db
   test "manages attachments multipart requests successfully", context do
 db_name = context[:db_name]
diff --git a/test/elixir/test/attachments_test.exs 
b/test/elixir/test/attachments_test.exs
index 8e7f7d3..d608847 100644
--- a/test/elixir/test/attachments_test.exs
+++ b/test/elixir/test/attachments_test.exs
@@ -115,6 +115,7 @@ defmodule AttachmentsTest do
 assert resp.headers["location"] == nil
   end
 
+  @tag :pending # Wrong Content-Type
   @tag :with_db
   test "saves binary", context do
 db_name = context[:db_name]
@@ -346,6 +347,7 @@ defmodule AttachmentsTest do
 assert resp.status_code == 400
   end
 
+  @tag :pending # HTTP 500
   @tag :with_db
   test "COUCHDB-809 - stubs should only require the 'stub' field", context do
 db_name = context[:db_nam

[couchdb] branch feature-ebtree-views updated (726bde4 -> e079a87)

2020-09-24 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a change to branch feature-ebtree-views
in repository https://gitbox.apache.org/repos/asf/couchdb.git.


 discard 726bde4  Add elixir tests for builtin reduce group levels
 discard 0f35508  Add test suite for reduce views
 discard 4d7dc40  Use ebtree for reduce functions
 discard ec3efaf  Upgrade legacy views
 discard 7368a72  Reimplement db wide view size tracking
 discard 1f773fb  Views on ebtree
 add 4e32f82  Views on ebtree
 add bd9486b  Reimplement db wide view size tracking
 add d035d8d  Upgrade legacy views
 add 54e9bcf  Use ebtree for reduce functions
 add cb28503  Add test suite for reduce views
 add e079a87  Add elixir tests for builtin reduce group levels

This update added new revisions after undoing existing revisions.
That is to say, some revisions that were in the old version of the
branch are not in the new version.  This situation occurs
when a user --force pushes a change and generates a repository
containing something like this:

 * -- * -- B -- O -- O -- O   (726bde4)
\
 N -- N -- N   refs/heads/feature-ebtree-views (e079a87)

You should already have received notification emails for all of the O
revisions, and so the following emails describe only the N revisions
from the common base, B.

Any revisions marked "omit" are not gone; other references still
refer to them.  Any revisions marked "discard" are gone forever.

No new revisions were added by this update.

Summary of changes:
 src/couch_views/src/couch_views_indexer.erl | 2 --
 1 file changed, 2 deletions(-)



[couchdb] branch feature-ebtree-views updated (f712e80 -> 726bde4)

2020-09-24 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a change to branch feature-ebtree-views
in repository https://gitbox.apache.org/repos/asf/couchdb.git.


 discard f712e80  Add test suite for reduce views
 discard 498a6bb  Use ebtree for reduce functions
 discard 57dbe74  Update legacy views
 discard ba38be9  Reimplement db wide view size tracking
 discard 9cd9fda  Views on ebtree
 discard 63482b9  Export fabric2_fdb:chunkify_binary/1,2
 discard ce2dade  Calculate external JSON size of a view row
 add f190677  Workaround dirty schedulers in run_queue stats (#3168)
 add fa3c3c8  Calculate external JSON size of a view row
 add 3b508e0  Export fabric2_fdb:chunkify_binary/1,2
 add 1f773fb  Views on ebtree
 add 7368a72  Reimplement db wide view size tracking
 add ec3efaf  Upgrade legacy views
 add 4d7dc40  Use ebtree for reduce functions
 add 0f35508  Add test suite for reduce views
 add 726bde4  Add elixir tests for builtin reduce group levels

This update added new revisions after undoing existing revisions.
That is to say, some revisions that were in the old version of the
branch are not in the new version.  This situation occurs
when a user --force pushes a change and generates a repository
containing something like this:

 * -- * -- B -- O -- O -- O   (f712e80)
\
 N -- N -- N   refs/heads/feature-ebtree-views (726bde4)

You should already have received notification emails for all of the O
revisions, and so the following emails describe only the N revisions
from the common base, B.

Any revisions marked "omit" are not gone; other references still
refer to them.  Any revisions marked "discard" are gone forever.

No new revisions were added by this update.

Summary of changes:
 rel/overlay/etc/default.ini|   4 +-
 src/chttpd/src/chttpd_node.erl |  17 +-
 src/couch_views/src/couch_views.erl|   4 +-
 src/couch_views/src/couch_views_fdb.erl| 594 ++---
 src/couch_views/src/couch_views_indexer.erl|   4 +-
 src/couch_views/src/couch_views_reader.erl |  12 +-
 .../{couch_views_fdb.erl => couch_views_trees.erl} | 431 +++
 src/couch_views/src/couch_views_updater.erl|   2 +-
 src/couch_views/test/couch_views_indexer_test.erl  |  24 +-
 src/couch_views/test/couch_views_red_test.erl  |  59 +-
 src/couch_views/test/couch_views_updater_test.erl  |   4 +-
 src/couch_views/test/couch_views_upgrade_test.erl  |   4 +-
 .../test/reduce_builtin_group_level_tests.exs  | 549 +++
 13 files changed, 724 insertions(+), 984 deletions(-)
 copy src/couch_views/src/{couch_views_fdb.erl => couch_views_trees.erl} (56%)
 create mode 100644 test/elixir/test/reduce_builtin_group_level_tests.exs



[couchdb] branch feature-ebtree-views-2 created (now 7701f2c)

2020-09-24 Thread davisp
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a change to branch feature-ebtree-views-2
in repository https://gitbox.apache.org/repos/asf/couchdb.git.


  at 7701f2c  Add test suite for reduce views

This branch includes the following new commits:

 new fa3c3c8  Calculate external JSON size of a view row
 new 3b508e0  Export fabric2_fdb:chunkify_binary/1,2
 new 1f773fb  Views on ebtree
 new ba2a426  Reimplement db wide view size tracking
 new 38ccbe1  Update legacy views
 new 89c175d  Use ebtree for reduce functions
 new 7701f2c  Add test suite for reduce views

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




  1   2   3   4   5   6   7   8   9   10   >