[1/2] couchdb-mango git commit: Revert "Enable bulk deletes"

2015-06-03 Thread tonysun83
Repository: couchdb-mango
Updated Branches:
  refs/heads/2651-delete-bulk-docs 6490184bf -> 3a8efbee5


Revert "Enable bulk deletes"

This reverts commit 6490184bf36c6eb04587d5fb3bd86923e62ec2b5.

COUCHDB-2651


Project: http://git-wip-us.apache.org/repos/asf/couchdb-mango/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-mango/commit/c8a2194c
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-mango/tree/c8a2194c
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-mango/diff/c8a2194c

Branch: refs/heads/2651-delete-bulk-docs
Commit: c8a2194c5e0121d5876e7917990e3983961b9681
Parents: 6490184
Author: Tony Sun 
Authored: Wed Jun 3 13:44:29 2015 -0400
Committer: Tony Sun 
Committed: Wed Jun 3 13:44:29 2015 -0400

--
 src/mango_error.erl|  7 
 src/mango_httpd.erl| 74 ++---
 src/mango_idx.erl  | 25 +-
 src/mango_opts.erl | 27 +--
 test/01-index-crud-test.py | 30 -
 test/mango.py  |  9 -
 6 files changed, 27 insertions(+), 145 deletions(-)
--


http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/c8a2194c/src/mango_error.erl
--
diff --git a/src/mango_error.erl b/src/mango_error.erl
index 6dcf7c8..babf564 100644
--- a/src/mango_error.erl
+++ b/src/mango_error.erl
@@ -110,13 +110,6 @@ info(mango_idx_view, {index_not_found, BadIdx}) ->
 fmt("JSON index ~s not found in this design doc.", [BadIdx])
 };
 
-info(mango_opts, {invalid_bulk_docs, Val}) ->
-{
-400,
-<<"invalid_bulk_docs">>,
-fmt("Bulk Delete requires an array of non-null docids. Docids: ~w",
-[Val])
-};
 info(mango_opts, {invalid_ejson, Val}) ->
 {
 400,

http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/c8a2194c/src/mango_httpd.erl
--
diff --git a/src/mango_httpd.erl b/src/mango_httpd.erl
index 671ffd2..28a1578 100644
--- a/src/mango_httpd.erl
+++ b/src/mango_httpd.erl
@@ -65,7 +65,7 @@ handle_index_req(#httpd{method='POST', path_parts=[_, 
_]}=Req, Db) ->
 {ok, DDoc} ->
 <<"exists">>;
 {ok, NewDDoc} ->
-CreateOpts = get_idx_w_opts(Opts),
+CreateOpts = get_idx_create_opts(Opts),
 case mango_crud:insert(Db, NewDDoc, CreateOpts) of
 {ok, [{RespProps}]} ->
 case lists:keyfind(error, 1, RespProps) of
@@ -80,28 +80,6 @@ handle_index_req(#httpd{method='POST', path_parts=[_, 
_]}=Req, Db) ->
 end,
chttpd:send_json(Req, {[{result, Status}, {id, Id}, {name, Name}]});
 
-%% Essentially we just iterate through the list of ddoc ids passed in and
-%% delete one by one. If an error occurs, all previous documents will be
-%% deleted, but an error will be thrown for the current ddoc id.
-handle_index_req(#httpd{method='POST', path_parts=[_, <<"_index">>,
-<<"_bulk_delete">>]}=Req, Db) ->
-{ok, Opts} = mango_opts:validate_bulk_delete(chttpd:json_body_obj(Req)),
-Idxs = mango_idx:list(Db),
-DDocs = get_bulk_delete_ddocs(Opts),
-DelOpts = get_idx_w_opts(Opts),
-{Success, Fail} = lists:foldl(fun(DDocId0, {Success0, Fail0}) ->
-DDocId = convert_to_design_id(DDocId0),
-Filt = fun(Idx) -> mango_idx:ddoc(Idx) == DDocId end,
-Id = {<<"id">>, DDocId},
-case mango_idx:delete(Filt, Db, Idxs, DelOpts) of
-{ok, true} ->
-{[{[Id, {<<"ok">>, true}]} | Success0], Fail0};
-{error, Error} ->
-{Success0, [{[Id, {<<"error">>, Error}]} | Fail0]}
-end
-end, {[], []}, DDocs),
-chttpd:send_json(Req, {[{<<"success">>, Success}, {<<"fail">>, Fail}]});
-
 handle_index_req(#httpd{method='DELETE',
 path_parts=[A, B, <<"_design">>, DDocId0, Type, Name]}=Req, Db) ->
 PathParts = [A, B, <<"_design/", DDocId0/binary>>, Type, Name],
@@ -109,22 +87,36 @@ handle_index_req(#httpd{method='DELETE',
 
 handle_index_req(#httpd{method='DELETE',
 path_parts=[_, _, DDocId0, Type, Name]}=Req, Db) ->
+DDocId = case DDocId0 of
+<<"_design/", _/binary>> -> DDocId0;
+_ -> <<"_design/", DDocId0/binary>>
+end,
 Idxs = mango_idx:list(Db),
-DDocId = convert_to_design_id(DDocId0),
-DelOpts = get_idx_del_opts(Req),
 Filt = fun(Idx) ->
 IsDDoc = mango_idx:ddoc(Idx) == DDocId,
 IsType = mango_idx:type(Idx) == Type,
 IsName = mango_idx:name(Idx) == Name,
 IsDDoc andalso IsType andalso IsName
 end,
-case mango_idx:delete(Filt, Db, Idxs, DelOpts) of
-{ok, true} ->
-chttpd:send_json(Req, {[{ok, true}]});
-{error, not_found} ->
-throw({not_found, missing});
-{error,

[2/2] couchdb-mango git commit: Enable bulk delete with fabric update_docs

2015-06-03 Thread tonysun83
Enable bulk delete with fabric update_docs

Rather than delete each doc one by one, we use fabric:update_docs
to bulk delete.

Fixes:COUCHDB-2651


Project: http://git-wip-us.apache.org/repos/asf/couchdb-mango/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-mango/commit/3a8efbee
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-mango/tree/3a8efbee
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-mango/diff/3a8efbee

Branch: refs/heads/2651-delete-bulk-docs
Commit: 3a8efbee5b954a38fb221a9653eb1682987aa2a0
Parents: c8a2194
Author: Tony Sun 
Authored: Wed Jun 3 15:53:21 2015 -0400
Committer: Tony Sun 
Committed: Wed Jun 3 15:53:21 2015 -0400

--
 src/mango_crud.erl |  3 +-
 src/mango_httpd.erl| 17 +++
 src/mango_idx.erl  | 62 +
 src/mango_opts.erl | 26 -
 src/mango_util.erl |  3 ++
 test/01-index-crud-test.py | 30 
 test/mango.py  |  9 ++
 7 files changed, 148 insertions(+), 2 deletions(-)
--


http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/3a8efbee/src/mango_crud.erl
--
diff --git a/src/mango_crud.erl b/src/mango_crud.erl
index 68c9d6c..c9eb845 100644
--- a/src/mango_crud.erl
+++ b/src/mango_crud.erl
@@ -21,7 +21,8 @@
 ]).
 
 -export([
-collect_cb/2
+collect_cb/2,
+maybe_add_user_ctx/2
 ]).
 
 

http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/3a8efbee/src/mango_httpd.erl
--
diff --git a/src/mango_httpd.erl b/src/mango_httpd.erl
index 28a1578..2fc2535 100644
--- a/src/mango_httpd.erl
+++ b/src/mango_httpd.erl
@@ -80,6 +80,14 @@ handle_index_req(#httpd{method='POST', path_parts=[_, 
_]}=Req, Db) ->
 end,
chttpd:send_json(Req, {[{result, Status}, {id, Id}, {name, Name}]});
 
+handle_index_req(#httpd{method='POST', path_parts=[_, <<"_index">>,
+<<"_bulk_delete">>]}=Req, Db) ->
+{ok, Opts} = mango_opts:validate_bulk_delete(chttpd:json_body_obj(Req)),
+DDocIds = get_bulk_delete_ddocs_ids(Opts),
+DelOpts = get_idx_create_opts(Opts),
+{Success, Error} = mango_idx:bulk_delete(Db, DDocIds, DelOpts),
+chttpd:send_json(Req, {[{<<"success">>, Success}, {<<"error">>, Error}]});
+
 handle_index_req(#httpd{method='DELETE',
 path_parts=[A, B, <<"_design">>, DDocId0, Type, Name]}=Req, Db) ->
 PathParts = [A, B, <<"_design/", DDocId0/binary>>, Type, Name],
@@ -157,6 +165,15 @@ get_idx_create_opts(Opts) ->
 end.
 
 
+get_bulk_delete_ddocs_ids(Opts) ->
+case lists:keyfind(docids, 1, Opts) of
+{docids, DDocs} when is_list(DDocs) ->
+DDocs;
+_ ->
+[]
+end.
+
+
 get_idx_del_opts(Req) ->
 try
 WStr = chttpd:qs_value(Req, "w", "2"),

http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/3a8efbee/src/mango_idx.erl
--
diff --git a/src/mango_idx.erl b/src/mango_idx.erl
index 1c15894..31d5e7d 100644
--- a/src/mango_idx.erl
+++ b/src/mango_idx.erl
@@ -26,6 +26,7 @@
 validate/1,
 add/2,
 remove/2,
+bulk_delete/3,
 from_ddoc/2,
 special/1,
 
@@ -134,6 +135,67 @@ remove(DDoc, Idx) ->
 {ok, NewDDoc#doc{body = Body}}.
 
 
+bulk_delete(Db, DDocIds, DelOpts0) ->
+DelOpts = mango_crud:maybe_add_user_ctx(Db, DelOpts0),
+{DeleteDocs, Errors} = lists:foldl(fun(DDocId0, {D, E}) ->
+Id = {<<"id">>, DDocId0},
+case get_bulk_delete_ddoc(Db, DDocId0) of
+not_found ->
+{D, [{[Id, {<<"error">>, <<"does not exist">>}]} | E]};
+invalid_ddoc_lang ->
+{D, [{[Id, {<<"error">>, <<"not a query doc">>}]} | E]};
+error_loading_doc ->
+{D, [{[Id, {<<"error">>, <<"loading doc">>}]} | E]};
+DDoc ->
+{[DDoc#doc{deleted = true, body = {[]}} | D], E }
+end
+end, {[], []}, DDocIds),
+case fabric:update_docs(Db, DeleteDocs, DelOpts) of
+{ok, Results} ->
+bulk_delete_results(lists:zip(DeleteDocs, Results), Errors);
+{accepted, Results} ->
+bulk_delete_results(lists:zip(DeleteDocs, Results), Errors);
+{aborted, Abort} ->
+bulk_delete_results(lists:zip(DeleteDocs, Abort), Errors)
+end.
+
+
+bulk_delete_results(DeleteResults, LoadErrors) ->
+{Success, Errors} = lists:foldl(fun({#doc{id=DDocId}, Result}, {S, E}) ->
+Id = {<<"id">>, DDocId},
+case Result of
+{_, {_Pos, _}} ->
+{[{[Id, {<<"ok">>, true}]} | S], E};
+{{_Id, _Rev}, Error} ->
+{_Code, ErrorStr, _Reason} = chttpd:error_info(Error),
+{S, [{[Id, {<<"e

fauxton commit: updated refs/heads/master to b4e5f53

2015-06-03 Thread michellep
Repository: couchdb-fauxton
Updated Branches:
  refs/heads/master 5d1cb4378 -> b4e5f5353


Add loading lines to active tasks
- Add tabs for filtering
- Add source sequence tray
- garrensmith helped me out a whole bunch with this


Project: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/commit/b4e5f535
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/tree/b4e5f535
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/diff/b4e5f535

Branch: refs/heads/master
Commit: b4e5f535309d6a807d1628d9cbf5eef91d105190
Parents: 5d1cb43
Author: Michelle Phung 
Authored: Wed Jun 3 09:50:28 2015 +0200
Committer: michelleph...@gmail.com 
Committed: Wed Jun 3 14:09:56 2015 -0400

--
 app/addons/activetasks/actions.js   |  18 +-
 app/addons/activetasks/actiontypes.js   |   3 +-
 .../activetasks/assets/less/activetasks.less| 171 +++
 app/addons/activetasks/components.react.jsx | 294 +--
 app/addons/activetasks/routes.js|   4 +-
 app/addons/activetasks/stores.js|  36 ++-
 .../tests/activetasks.componentsSpec.react.jsx  |  25 +-
 .../activetasks/tests/activetasks.storesSpec.js |  45 +--
 app/addons/fauxton/components.react.jsx |  35 +++
 9 files changed, 376 insertions(+), 255 deletions(-)
--


http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/b4e5f535/app/addons/activetasks/actions.js
--
diff --git a/app/addons/activetasks/actions.js 
b/app/addons/activetasks/actions.js
index 74fae94..55469ab 100644
--- a/app/addons/activetasks/actions.js
+++ b/app/addons/activetasks/actions.js
@@ -16,17 +16,17 @@ define([
 ],
 function (FauxtonAPI, ActionTypes, Resources) {
   return {
-fetchAndSetActiveTasks: function (options) {
-  var activeTasks = options;
-
+init: function (activeTasks) {
+  this.fetchAndSetActiveTasks(activeTasks.table, activeTasks);
   FauxtonAPI.when(activeTasks.fetch()).then(function () {
-this.init(activeTasks.table, activeTasks);
+this.fetchAndSetActiveTasks(activeTasks.table, activeTasks);
+this.setActiveTaskIsLoading(false);
   }.bind(this));
 },
 
-init: function (collection, backboneCollection) {
+fetchAndSetActiveTasks: function (collection, backboneCollection) {
   FauxtonAPI.dispatch({
-type: ActionTypes.ACTIVE_TASKS_INIT,
+type: ActionTypes.ACTIVE_TASKS_FETCH_AND_SET,
 options: {
   collectionTable: collection,
   backboneCollection: backboneCollection
@@ -64,6 +64,12 @@ function (FauxtonAPI, ActionTypes, Resources) {
   columnName: columnName
 }
   });
+},
+setActiveTaskIsLoading: function (boolean) {
+  FauxtonAPI.dispatch({
+type: ActionTypes.ACTIVE_TASKS_SET_IS_LOADING,
+options: boolean
+  });
 }
   };
 });

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/b4e5f535/app/addons/activetasks/actiontypes.js
--
diff --git a/app/addons/activetasks/actiontypes.js 
b/app/addons/activetasks/actiontypes.js
index 8cd2838..cdba87d 100644
--- a/app/addons/activetasks/actiontypes.js
+++ b/app/addons/activetasks/actiontypes.js
@@ -16,6 +16,7 @@ define([], function () {
 ACTIVE_TASKS_SET_COLLECTION: 'ACTIVE_TASKS_SET_COLLECTION',
 ACTIVE_TASKS_SET_SEARCH_TERM: 'ACTIVE_TASKS_SET_SEARCH_TERM',
 ACTIVE_TASKS_SORT_BY_COLUMN_HEADER: 'ACTIVE_TASKS_SORT_BY_COLUMN_HEADER',
-ACTIVE_TASKS_INIT: 'ACTIVE_TASKS_INIT'
+ACTIVE_TASKS_FETCH_AND_SET: 'ACTIVE_TASKS_FETCH_AND_SET',
+ACTIVE_TASKS_SET_IS_LOADING: 'ACTIVE_TASKS_SET_IS_LOADING'
   };
 });

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/b4e5f535/app/addons/activetasks/assets/less/activetasks.less
--
diff --git a/app/addons/activetasks/assets/less/activetasks.less 
b/app/addons/activetasks/assets/less/activetasks.less
index 1116671..e11c0a8 100644
--- a/app/addons/activetasks/assets/less/activetasks.less
+++ b/app/addons/activetasks/assets/less/activetasks.less
@@ -10,6 +10,10 @@
 // License for the specific language governing permissions and limitations 
under
 // the License.
 
+@import "../../../../../assets/less/bootstrap/variables.less";
+@import "../../../../../assets/less/variables.less";
+@import "../../../../../assets/less/bootstrap/mixins.less";
+
 .task-tabs li,
 .active-tasks th {
   cursor: pointer;
@@ -65,7 +69,7 @@
 }
 
 .no-matching-database-on-search {
-  color: #e33f3b;
+  color: #af2d24;
 }
 
 p.multiline-active-tasks-message {
@@ -88,67 +92,63 @@ p.multiline-active-tasks-message {
   }
 }
 
-.dashboard-lower-menu {
-  padding-top

couch commit: updated refs/heads/master to 3d97e77

2015-06-03 Thread rnewson
Repository: couchdb-couch
Updated Branches:
  refs/heads/master e19b262d4 -> 3d97e7792


Replace password_scheme and iterations field

Previously we introduced duplicates

COUCHDB-2710


Project: http://git-wip-us.apache.org/repos/asf/couchdb-couch/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-couch/commit/3d97e779
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-couch/tree/3d97e779
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-couch/diff/3d97e779

Branch: refs/heads/master
Commit: 3d97e7792ca081dcd66e5ea5561d3a09309cbd53
Parents: e19b262
Author: Robert Newson 
Authored: Wed Jun 3 19:38:13 2015 +0100
Committer: Robert Newson 
Committed: Wed Jun 3 19:38:13 2015 +0100

--
 src/couch_users_db.erl | 11 ++-
 1 file changed, 6 insertions(+), 5 deletions(-)
--


http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/3d97e779/src/couch_users_db.erl
--
diff --git a/src/couch_users_db.erl b/src/couch_users_db.erl
index 3b76862..ade1955 100644
--- a/src/couch_users_db.erl
+++ b/src/couch_users_db.erl
@@ -66,11 +66,12 @@ save_doc(#doc{body={Body}} = Doc) ->
 Iterations = list_to_integer(config:get("couch_httpd_auth", 
"iterations", "1000")),
 Salt = couch_uuids:random(),
 DerivedKey = couch_passwords:pbkdf2(ClearPassword, Salt, Iterations),
-Body0 = [{?PASSWORD_SCHEME, ?PBKDF2}, {?ITERATIONS, Iterations}|Body],
-Body1 = ?replace(Body0, ?DERIVED_KEY, DerivedKey),
-Body2 = ?replace(Body1, ?SALT, Salt),
-Body3 = proplists:delete(?PASSWORD, Body2),
-Doc#doc{body={Body3}}
+Body0 = ?replace(Body, ?PASSWORD_SCHEME, ?PBKDF2),
+Body1 = ?replace(Body0, ?ITERATIONS, Iterations),
+Body2 = ?replace(Body1, ?DERIVED_KEY, DerivedKey),
+Body3 = ?replace(Body2, ?SALT, Salt),
+Body4 = proplists:delete(?PASSWORD, Body3),
+Doc#doc{body={Body4}}
 end.
 
 % If the doc is a design doc



[3/3] fabric commit: updated refs/heads/merge-diff-from-cloudant-fork to ece2b2e

2015-06-03 Thread mikewallace
export dbname/1

BugzID: 45853

This is a cherry-pick of:

https://github.com/cloudant/fabric/commit/818dd09e9ea645e866fc62fd1a4302ce73b2422a


Project: http://git-wip-us.apache.org/repos/asf/couchdb-fabric/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-fabric/commit/ece2b2ed
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-fabric/tree/ece2b2ed
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-fabric/diff/ece2b2ed

Branch: refs/heads/merge-diff-from-cloudant-fork
Commit: ece2b2ed9114d454eea79d8788f8d0c01f172ed9
Parents: 383f8f4
Author: Robert Newson 
Authored: Thu Apr 9 23:07:19 2015 +0100
Committer: Mike Wallace 
Committed: Wed Jun 3 15:02:32 2015 +0100

--
 src/fabric.erl | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
--


http://git-wip-us.apache.org/repos/asf/couchdb-fabric/blob/ece2b2ed/src/fabric.erl
--
diff --git a/src/fabric.erl b/src/fabric.erl
index 26b9f62..c3a95fb 100644
--- a/src/fabric.erl
+++ b/src/fabric.erl
@@ -33,7 +33,7 @@
 
 % miscellany
 -export([design_docs/1, reset_validation_funs/1, cleanup_index_files/0,
-cleanup_index_files/1]).
+cleanup_index_files/1, dbname/1]).
 
 -include_lib("fabric/include/fabric.hrl").
 



[2/3] fabric commit: updated refs/heads/merge-diff-from-cloudant-fork to ece2b2e

2015-06-03 Thread mikewallace
Add ability to gracefully terminate existing changes feeds

Calling fabric:end_changes() will cause all current changes
feeds to gracefully exit without preventing new changes requests from
starting (unlike maintenance_mode).

BugzID: 45762

This is a cherry-pick of:

https://github.com/cloudant/fabric/commit/1b45cede8f11e209f28e3d06b9fda4cbdcd719cc

Conflicts:
src/fabric.erl
src/fabric_view_changes.erl


Project: http://git-wip-us.apache.org/repos/asf/couchdb-fabric/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-fabric/commit/383f8f4d
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-fabric/tree/383f8f4d
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-fabric/diff/383f8f4d

Branch: refs/heads/merge-diff-from-cloudant-fork
Commit: 383f8f4dc46737fac646a6d90ff03b64c0d94109
Parents: d7d6be8
Author: Robert Newson 
Authored: Sun Mar 29 13:38:38 2015 +0100
Committer: Mike Wallace 
Committed: Wed Jun 3 15:00:56 2015 +0100

--
 src/fabric.erl  |  6 +-
 src/fabric_view_changes.erl | 17 -
 2 files changed, 21 insertions(+), 2 deletions(-)
--


http://git-wip-us.apache.org/repos/asf/couchdb-fabric/blob/383f8f4d/src/fabric.erl
--
diff --git a/src/fabric.erl b/src/fabric.erl
index 25205f8..26b9f62 100644
--- a/src/fabric.erl
+++ b/src/fabric.erl
@@ -29,7 +29,7 @@
 
 % Views
 -export([all_docs/4, all_docs/5, changes/4, query_view/3, query_view/4,
-query_view/6, get_view_group_info/2]).
+query_view/6, get_view_group_info/2, end_changes/0]).
 
 % miscellany
 -export([design_docs/1, reset_validation_funs/1, cleanup_index_files/0,
@@ -362,6 +362,10 @@ query_view(DbName, DDoc, ViewName, Callback, Acc0, 
QueryArgs0) ->
 get_view_group_info(DbName, DesignId) ->
 fabric_group_info:go(dbname(DbName), design_doc(DesignId)).
 
+-spec end_changes() -> ok.
+end_changes() ->
+fabric_view_changes:increment_changes_epoch().
+
 %% @doc retrieve all the design docs from a database
 -spec design_docs(dbname()) -> {ok, [json_obj()]}.
 design_docs(DbName) ->

http://git-wip-us.apache.org/repos/asf/couchdb-fabric/blob/383f8f4d/src/fabric_view_changes.erl
--
diff --git a/src/fabric_view_changes.erl b/src/fabric_view_changes.erl
index 92d08e7..7ec 100644
--- a/src/fabric_view_changes.erl
+++ b/src/fabric_view_changes.erl
@@ -13,6 +13,7 @@
 -module(fabric_view_changes).
 
 -export([go/5, pack_seqs/1, unpack_seqs/2]).
+-export([increment_changes_epoch/0]).
 
 %% exported for upgrade purposes.
 -export([keep_sending_changes/8]).
@@ -37,6 +38,7 @@ go(DbName, Feed, Options, Callback, Acc0) when Feed == 
"continuous" orelse
 UpdateListener = {spawn_link(fabric_db_update_listener, go,
  [Parent, Ref, DbName, Timeout]),
   Ref},
+put(changes_epoch, get_changes_epoch()),
 try
 keep_sending_changes(
 DbName,
@@ -86,8 +88,9 @@ keep_sending_changes(DbName, Args, Callback, Seqs, AccIn, 
Timeout, UpListen, T0)
 } = Collector,
 LastSeq = pack_seqs(NewSeqs),
 MaintenanceMode = config:get("couchdb", "maintenance_mode"),
+NewEpoch = get_changes_epoch() > erlang:get(changes_epoch),
 if Limit > Limit2, Feed == "longpoll";
-  MaintenanceMode == "true"; MaintenanceMode == "nolb" ->
+  MaintenanceMode == "true"; MaintenanceMode == "nolb"; NewEpoch ->
 Callback({stop, LastSeq, pending_count(Offset)}, AccOut);
 true ->
 WaitForUpdate = wait_db_updated(UpListen),
@@ -459,6 +462,18 @@ validate_start_seq(DbName, Seq) ->
 {error, {bad_request, Reason}}
 end.
 
+get_changes_epoch() ->
+case application:get_env(fabric, changes_epoch) of
+undefined ->
+increment_changes_epoch(),
+get_changes_epoch();
+{ok, Epoch} ->
+Epoch
+end.
+
+increment_changes_epoch() ->
+application:set_env(fabric, changes_epoch, os:timestamp()).
+
 unpack_seqs_test() ->
 meck:new(mem3),
 meck:new(fabric_view),



[1/3] fabric commit: updated refs/heads/merge-diff-from-cloudant-fork to ece2b2e

2015-06-03 Thread mikewallace
Repository: couchdb-fabric
Updated Branches:
  refs/heads/merge-diff-from-cloudant-fork [created] ece2b2ed9


Provide an access to a document info

The functions `get_doc_info/3` and `get_full_doc_info/3` were
added to API to provide an access to the records `#doc_info{}`
and `#full_doc_info{}` accordingly.

The functions are re-using `fabric_open_doc` coordinator
and consequently are the subject of the same read quorum rules
as `open_doc/3` function. However the info functions do not trigger
read repair on a not fully complete quorum.

Function `get_full_doc_info/3` accepts an option `deleted` to
allow to provide an information for a deleted document,
similar to `open_doc/3`.

FogBugz: 12933

This is a cherry-pick of:

https://github.com/cloudant/fabric/commit/c85569287ad8f86122b47775adc2ab9218db0322

Conflicts:
src/fabric_rpc.erl


Project: http://git-wip-us.apache.org/repos/asf/couchdb-fabric/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-fabric/commit/d7d6be85
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-fabric/tree/d7d6be85
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-fabric/diff/d7d6be85

Branch: refs/heads/merge-diff-from-cloudant-fork
Commit: d7d6be8535443fd3ddbe65c0a6a35534b4b98e29
Parents: d44f7fb
Author: Eric Avdey 
Authored: Mon Nov 10 20:12:42 2014 -0400
Committer: Mike Wallace 
Committed: Wed Jun 3 14:54:21 2015 +0100

--
 src/fabric.erl  | 34 --
 src/fabric_doc_open.erl | 68 +---
 src/fabric_rpc.erl  | 10 +--
 3 files changed, 103 insertions(+), 9 deletions(-)
--


http://git-wip-us.apache.org/repos/asf/couchdb-fabric/blob/d7d6be85/src/fabric.erl
--
diff --git a/src/fabric.erl b/src/fabric.erl
index 958e63c..25205f8 100644
--- a/src/fabric.erl
+++ b/src/fabric.erl
@@ -23,8 +23,9 @@
 get_security/2, get_all_security/1, get_all_security/2]).
 
 % Documents
--export([open_doc/3, open_revs/4, get_missing_revs/2, get_missing_revs/3,
-update_doc/3, update_docs/3, purge_docs/2, att_receiver/2]).
+-export([open_doc/3, open_revs/4, get_doc_info/3, get_full_doc_info/3,
+get_missing_revs/2, get_missing_revs/3, update_doc/3, update_docs/3,
+purge_docs/2, att_receiver/2]).
 
 % Views
 -export([all_docs/4, all_docs/5, changes/4, query_view/3, query_view/4,
@@ -161,7 +162,12 @@ get_all_security(DbName, Options) ->
 {error, any()} |
 {error, any() | any()}.
 open_doc(DbName, Id, Options) ->
-fabric_doc_open:go(dbname(DbName), docid(Id), opts(Options)).
+case proplists:get_value(doc_info, Options) of
+undefined ->
+fabric_doc_open:go(dbname(DbName), docid(Id), opts(Options));
+Else ->
+{error, {invalid_option, {doc_info, Else}}}
+end.
 
 %% @doc retrieve a collection of revisions, possible all
 -spec open_revs(dbname(), docid(), [revision()] | all, [option()]) ->
@@ -172,6 +178,28 @@ open_doc(DbName, Id, Options) ->
 open_revs(DbName, Id, Revs, Options) ->
 fabric_doc_open_revs:go(dbname(DbName), docid(Id), Revs, opts(Options)).
 
+%% @doc Retrieves an information on a document with a given id
+-spec get_doc_info(dbname(), docid(), [options()]) ->
+{ok, #doc_info{}} |
+{not_found, missing} |
+{timeout, any()} |
+{error, any()} |
+{error, any() | any()}.
+get_doc_info(DbName, Id, Options) ->
+Options1 = [doc_info|Options],
+fabric_doc_open:go(dbname(DbName), docid(Id), opts(Options1)).
+
+%% @doc Retrieves a full information on a document with a given id
+-spec get_full_doc_info(dbname(), docid(), [options()]) ->
+{ok, #full_doc_info{}} |
+{not_found, missing | deleted} |
+{timeout, any()} |
+{error, any()} |
+{error, any() | any()}.
+get_full_doc_info(DbName, Id, Options) ->
+Options1 = [{doc_info, full}|Options],
+fabric_doc_open:go(dbname(DbName), docid(Id), opts(Options1)).
+
 %% @equiv get_missing_revs(DbName, IdsRevs, [])
 get_missing_revs(DbName, IdsRevs) ->
 get_missing_revs(DbName, IdsRevs, []).

http://git-wip-us.apache.org/repos/asf/couchdb-fabric/blob/d7d6be85/src/fabric_doc_open.erl
--
diff --git a/src/fabric_doc_open.erl b/src/fabric_doc_open.erl
index c7d90a4..1607946 100644
--- a/src/fabric_doc_open.erl
+++ b/src/fabric_doc_open.erl
@@ -30,7 +30,12 @@
 
 
 go(DbName, Id, Options) ->
-Workers = fabric_util:submit_jobs(mem3:shards(DbName,Id), open_doc,
+Handler = case proplists:get_value(doc_info, Options) of
+true -> get_doc_info;
+full -> get_full_doc_info;
+undefined -> open_doc
+end,
+Workers = fabric_util:submit_jobs(mem3:shards(DbName,Id), Handler,
 [Id, [deleted|Options]]),
 SuppressDeletedDoc = not lists:member(deleted, Options),
 N = mem3:n(DbN

[3/3] config commit: updated refs/heads/2708-stronger-testing-for-config-set to ee652d2

2015-06-03 Thread mikewallace
[squash] apply stronger testing to config:get/3


Project: http://git-wip-us.apache.org/repos/asf/couchdb-config/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-config/commit/ee652d2e
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-config/tree/ee652d2e
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-config/diff/ee652d2e

Branch: refs/heads/2708-stronger-testing-for-config-set
Commit: ee652d2ee00ab5b9afea28c2a2a529e4eacf4195
Parents: 6566dd4
Author: Mike Wallace 
Authored: Wed Jun 3 12:23:20 2015 +0100
Committer: Mike Wallace 
Committed: Wed Jun 3 12:37:03 2015 +0100

--
 src/config.erl | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
--


http://git-wip-us.apache.org/repos/asf/couchdb-config/blob/ee652d2e/src/config.erl
--
diff --git a/src/config.erl b/src/config.erl
index 301d4e1..908dee7 100644
--- a/src/config.erl
+++ b/src/config.erl
@@ -137,7 +137,9 @@ get(Section, Key) ->
 
 get(Section, Key, Default) when is_binary(Section) and is_binary(Key) ->
 ?MODULE:get(binary_to_list(Section), binary_to_list(Key), Default);
-get(Section, Key, Default) when is_list(Section), is_list(Key) ->
+get(Section, Key, Default) ->
+assert_string(Section),
+assert_string(Key),
 case ets:lookup(?MODULE, {Section, Key}) of
 [] when Default == undefined -> Default;
 [] when is_boolean(Default) -> Default;



[2/3] config commit: updated refs/heads/2708-stronger-testing-for-config-set to ee652d2

2015-06-03 Thread mikewallace
[squash] Add tests for add stronger config set/get/delete testing


Project: http://git-wip-us.apache.org/repos/asf/couchdb-config/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-config/commit/6566dd43
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-config/tree/6566dd43
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-config/diff/6566dd43

Branch: refs/heads/2708-stronger-testing-for-config-set
Commit: 6566dd43c6f2a6bc8c5c737be2c41477833a3065
Parents: f695b78
Author: Mike Wallace 
Authored: Wed Jun 3 12:16:58 2015 +0100
Committer: Mike Wallace 
Committed: Wed Jun 3 12:37:03 2015 +0100

--
 test/config_tests.erl | 25 ++---
 1 file changed, 18 insertions(+), 7 deletions(-)
--


http://git-wip-us.apache.org/repos/asf/couchdb-config/blob/6566dd43/test/config_tests.erl
--
diff --git a/test/config_tests.erl b/test/config_tests.erl
index c823d3e..778e383 100644
--- a/test/config_tests.erl
+++ b/test/config_tests.erl
@@ -116,7 +116,7 @@ config_get_tests() ->
 should_return_undefined_atom_on_missed_option(),
 should_return_custom_default_value_on_missed_option(),
 should_only_return_default_on_missed_option(),
-should_fail_to_get_binary_value(),
+should_fail_to_get_non_string_value(),
 should_return_any_supported_default()
 ]
 }
@@ -131,7 +131,7 @@ config_set_tests() ->
 [
 should_update_option(),
 should_create_new_section(),
-should_fail_to_set_binary_value()
+should_fail_to_set_non_string_value()
 ]
 }
 }.
@@ -144,7 +144,8 @@ config_del_tests() ->
 fun setup/0, fun teardown/1,
 [
 should_return_undefined_atom_after_option_deletion(),
-should_be_ok_on_deleting_unknown_options()
+should_be_ok_on_deleting_unknown_options(),
+should_fail_to_delete_non_string_value()
 ]
 }
 }.
@@ -243,9 +244,11 @@ should_only_return_default_on_missed_option() ->
 ?_assertEqual("0",
   config:get("httpd", "port", "bar")).
 
-should_fail_to_get_binary_value() ->
+should_fail_to_get_non_string_value() ->
 ?_assertException(error, badarg,
-  config:get(<<"foo">>, <<"bar">>, <<"baz">>)).
+  config:get(<<"foo">>, <<"bar">>, <<"baz">>)),
+?_assertException(error, badarg,
+  config:get([f, o, o], [b, a, r], [b, a, z])).
 
 should_return_any_supported_default() ->
 Values = [undefined, "list", true, false, 0.1, 1],
@@ -269,9 +272,11 @@ should_create_new_section() ->
 config:get("new_section", "bizzle")
 end).
 
-should_fail_to_set_binary_value() ->
+should_fail_to_set_non_string_value() ->
+?_assertException(error, badarg,
+config:set(<<"foo">>, <<"bar">>, <<"baz">>, false)),
 ?_assertException(error, badarg,
-config:set(<<"foo">>, <<"bar">>, <<"baz">>, false)).
+config:set([f, o, o], [b, a, r], [b, a, z], false)).
 
 should_return_undefined_atom_after_option_deletion() ->
 ?_assertEqual(undefined,
@@ -283,6 +288,12 @@ should_return_undefined_atom_after_option_deletion() ->
 should_be_ok_on_deleting_unknown_options() ->
 ?_assertEqual(ok, config:delete("zoo", "boo", false)).
 
+should_fail_to_delete_non_string_value() ->
+?_assertException(error, badarg,
+config:delete(<<"foo">>, <<"bar">>, false)),
+?_assertException(error, badarg,
+config:delete([f, o, o], [b, a, r], false)).
+
 should_ensure_in_defaults(_, _) ->
 ?_test(begin
 ?assertEqual("500",



[1/3] config commit: updated refs/heads/2708-stronger-testing-for-config-set to ee652d2

2015-06-03 Thread mikewallace
Repository: couchdb-config
Updated Branches:
  refs/heads/2708-stronger-testing-for-config-set [created] ee652d2ee


strong testing for config:set calls

Closes COUCHDB-2708.

This is a cherry-pick of:

https://github.com/cloudant/config/commit/d48a2bfdaa7c7c1e0004835c42e98d6794050317

Conflicts:
src/config.erl


Project: http://git-wip-us.apache.org/repos/asf/couchdb-config/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-config/commit/f695b782
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-config/tree/f695b782
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-config/diff/f695b782

Branch: refs/heads/2708-stronger-testing-for-config-set
Commit: f695b782f563de65913e8cd9d7a2597ef395369e
Parents: b281825
Author: Robert Newson 
Authored: Fri Nov 7 17:47:12 2014 +
Committer: Mike Wallace 
Committed: Wed Jun 3 12:36:41 2015 +0100

--
 src/config.erl | 19 ---
 1 file changed, 16 insertions(+), 3 deletions(-)
--


http://git-wip-us.apache.org/repos/asf/couchdb-config/blob/f695b782/src/config.erl
--
diff --git a/src/config.erl b/src/config.erl
index a24bb27..301d4e1 100644
--- a/src/config.erl
+++ b/src/config.erl
@@ -158,8 +158,11 @@ set(Section, Key, Value, Reason) ->
 
 set(Sec, Key, Val, Persist, Reason) when is_binary(Sec) and is_binary(Key) ->
 ?MODULE:set(binary_to_list(Sec), binary_to_list(Key), Val, Persist, 
Reason);
-set(Section, Key, Value, Persist, Reason)
-when is_list(Section), is_list(Key), is_list(Value) ->
+set(Section, Key, Value, Persist, Reason) when is_boolean(Persist) ->
+assert_string(Section),
+assert_string(Key),
+assert_string(Value),
+if Reason == nil -> ok; true -> assert_string(Reason) end,
 gen_server:call(?MODULE, {set, Section, Key, Value, Persist, Reason});
 set(_Sec, _Key, _Val, _Persist, _Reason) ->
 error(badarg).
@@ -177,9 +180,19 @@ delete(Section, Key, Reason) ->
 
 delete(Sec, Key, Persist, Reason) when is_binary(Sec) and is_binary(Key) ->
 delete(binary_to_list(Sec), binary_to_list(Key), Persist, Reason);
-delete(Section, Key, Persist, Reason) when is_list(Section), is_list(Key) ->
+delete(Section, Key, Persist, Reason) when is_boolean(Persist) ->
+assert_string(Section),
+assert_string(Key),
+if Reason == nil -> ok; true -> assert_string(Reason) end,
 gen_server:call(?MODULE, {delete, Section, Key, Persist, Reason}).
 
+assert_string(Term) ->
+case io_lib:printable_list(Term) of
+true ->
+ok;
+false ->
+error(badarg)
+end.
 
 listen_for_changes(CallbackModule, InitialState) ->
 gen_server:call(?MODULE, {listen_for_changes, CallbackModule, 
InitialState}).



fauxton commit: updated refs/heads/master to 5d1cb43

2015-06-03 Thread garren
Repository: couchdb-fauxton
Updated Branches:
  refs/heads/master 79c20e43b -> 5d1cb4378


Fix code editor test name


Project: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/commit/5d1cb437
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/tree/5d1cb437
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/diff/5d1cb437

Branch: refs/heads/master
Commit: 5d1cb4378a79912eb210c45f1e03142bbb953700
Parents: 79c20e4
Author: Garren Smith 
Authored: Wed Jun 3 09:16:51 2015 +0200
Committer: Garren Smith 
Committed: Wed Jun 3 09:21:51 2015 +0200

--
 app/addons/components/tests/codeEditorSpec.jsx  | 134 ---
 .../components/tests/codeEditorSpec.react.jsx   | 134 +++
 2 files changed, 134 insertions(+), 134 deletions(-)
--


http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/5d1cb437/app/addons/components/tests/codeEditorSpec.jsx
--
diff --git a/app/addons/components/tests/codeEditorSpec.jsx 
b/app/addons/components/tests/codeEditorSpec.jsx
deleted file mode 100644
index 73f9ce1..000
--- a/app/addons/components/tests/codeEditorSpec.jsx
+++ /dev/null
@@ -1,134 +0,0 @@
-// 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.
-define([
-  'api',
-  'addons/components/react-components.react',
-
-  'testUtils',
-  'react'
-], function (FauxtonAPI, ReactComponents, utils, React) {
-
-  var assert = utils.assert;
-  var TestUtils = React.addons.TestUtils;
-  var code = 'function (doc) {\n  emit(doc._id, 1);\n}';
-  var code2 = 'function (doc) {\n if(doc._id) { \n emit(doc._id, 2); \n } \n}';
-
-  describe('Code Editor', function () {
-var container, codeEditorEl, spy;
-
-beforeEach(function () {
-  spy = sinon.spy();
-  container = document.createElement('div');
-  codeEditorEl = TestUtils.renderIntoDocument(
-,
-container
-  );
-});
-
-afterEach(function () {
-  React.unmountComponentAtNode(container);
-});
-
-describe('Tracking edits', function () {
-
-  it('no change on mount', function () {
-assert.notOk(codeEditorEl.hasChanged());
-  });
-
-  it('detects change on user input', function () {
-codeEditorEl.editor.setValue(code2, -1);
-
-assert.ok(codeEditorEl.hasChanged());
-  });
-
-});
-
-describe('onBlur', function () {
-
-  it('calls changed function', function () {
-codeEditorEl.editor._emit('blur');
-assert.ok(spy.calledOnce);
-  });
-
-});
-
-describe('setHeightToLineCount', function () {
-
-  beforeEach(function () {
-codeEditorEl = TestUtils.renderIntoDocument(
-  ,
-  container
-);
-
-  });
-
-  it('sets line height correctly for non full page', function () {
-var spy = sinon.spy(codeEditorEl.editor, 'setOptions');
-
-codeEditorEl.setHeightToLineCount();
-assert.ok(spy.calledOnce);
-assert.equal(spy.getCall(0).args[0].maxLines, 3);
-  });
-
-});
-
-describe('removeIncorrectAnnotations', function () {
-
-  beforeEach(function () {
-codeEditorEl = TestUtils.renderIntoDocument(
-  ,
-  container
-);
-
-  });
-
-  it('removes default errors that do not apply to CouchDB Views', function 
() {
-assert.equal(codeEditorEl.getAnnotations(), 0);
-  });
-
-});
-
-describe('setEditorValue', function () {
-
-  it('sets new code', function () {
-codeEditorEl = TestUtils.renderIntoDocument(
-  ,
-  container
-);
-
-codeEditorEl.setEditorValue(code2);
-assert.deepEqual(codeEditorEl.getValue(), code2);
-  });
-
-});
-
-describe('showEditorOnly', function () {
-
-  it('only shows editor when showEditorOnly=true', function () {
-codeEditorEl = TestUtils.renderIntoDocument(
-  ,
-  container
-);
-assert.notOk($(codeEditorEl.getDOMNode()).hasClass('control-group'));
-  });
-
-  it('shows everything by default', function () {
-var codeEditorEl = TestUtils.renderIntoDocument(
-  ,
-  container
-);
-assert.ok($(codeEditorEl.getDOMNode()).hasClass('control-gro