You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by to...@apache.org on 2015/10/05 21:45:27 UTC

[1/5] couchdb-mango git commit: Fix comparison operators for strings

Repository: couchdb-mango
Updated Branches:
  refs/heads/2816-malformed-docs 2d26f2295 -> 87020c220 (forced update)


Fix comparison operators for strings

The comparison operators $lt, $lte, $gt, and $gte were incorrectly
using lower bound and upper bound values when comparing text.
For strings, we modify the the lower bound limit to be an empty string,
and the upper bound to be the highest unicode value.

COUCHDB-2808


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

Branch: refs/heads/2816-malformed-docs
Commit: bb595d01018f1f8e67623606f625a13ccf6cb239
Parents: f924032
Author: Tony Sun <to...@cloudant.com>
Authored: Mon Sep 14 17:57:28 2015 -0700
Committer: Tony Sun <to...@cloudant.com>
Committed: Mon Sep 14 18:17:53 2015 -0700

----------------------------------------------------------------------
 src/mango_selector_text.erl | 21 +++++++++++++++++----
 test/06-basic-text-test.py  | 16 ++++++++++++++++
 2 files changed, 33 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/bb595d01/src/mango_selector_text.erl
----------------------------------------------------------------------
diff --git a/src/mango_selector_text.erl b/src/mango_selector_text.erl
index 9450dfe..b6e1f09 100644
--- a/src/mango_selector_text.erl
+++ b/src/mango_selector_text.erl
@@ -267,13 +267,26 @@ make_field(Path, Arg) ->
 
 
 range(lt, Arg) ->
-    [<<"[-Infinity TO ">>, value_str(Arg), <<"}">>];
+    Min = get_range(min, Arg),
+    [<<"[", Min/binary, " TO ">>, value_str(Arg), <<"}">>];
 range(lte, Arg) ->
-    [<<"[-Infinity TO ">>, value_str(Arg), <<"]">>];
+    Min = get_range(min, Arg),
+    [<<"[", Min/binary, " TO ">>, value_str(Arg), <<"]">>];
 range(gte, Arg) ->
-    [<<"[">>, value_str(Arg), <<" TO Infinity]">>];
+    Max = get_range(max, Arg),
+    [<<"[">>, value_str(Arg), <<" TO ", Max/binary, "]">>];
 range(gt, Arg) ->
-    [<<"{">>, value_str(Arg), <<" TO Infinity]">>].
+    Max = get_range(max, Arg),
+    [<<"{">>, value_str(Arg), <<" TO ", Max/binary, "]">>].
+
+get_range(min, Arg) when is_number(Arg) ->
+    <<"-Infinity">>;
+get_range(min, _Arg) ->
+    <<"\"\"">>;
+get_range(max, Arg) when is_number(Arg) ->
+    <<"Infinity">>;
+get_range(max, _Arg) ->
+    <<"\u0x10FFFF">>.
 
 
 field_exists_query(Path) ->

http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/bb595d01/test/06-basic-text-test.py
----------------------------------------------------------------------
diff --git a/test/06-basic-text-test.py b/test/06-basic-text-test.py
index c60779e..1e3d5df 100644
--- a/test/06-basic-text-test.py
+++ b/test/06-basic-text-test.py
@@ -96,6 +96,10 @@ class BasicTextTests(mango.UserDocsTextTests):
         for d in docs:
             assert d["user_id"] in (1, 7, 9)
 
+        docs = self.db.find({"company": {"$lt": "Dreamia"}})
+        assert len(docs) == 1
+        assert docs[0]["company"] == "Affluex"
+
     def test_lte(self):
         docs = self.db.find({"age": {"$lte": 21}})
         assert len(docs) == 0
@@ -109,6 +113,11 @@ class BasicTextTests(mango.UserDocsTextTests):
         for d in docs:
             assert d["user_id"] in (1, 7, 9)
 
+        docs = self.db.find({"company": {"$lte": "Dreamia"}})
+        assert len(docs) == 2
+        for d in docs:
+            assert d["user_id"] in (0, 11)
+
     def test_eq(self):
         docs = self.db.find({"age": 21})
         assert len(docs) == 0
@@ -149,6 +158,9 @@ class BasicTextTests(mango.UserDocsTextTests):
         docs = self.db.find({"age": {"$gt": 79}})
         assert len(docs) == 0
 
+        docs = self.db.find({"company": {"$gt": "Zialactic"}})
+        assert len(docs) == 0
+
     def test_gte(self):
         docs = self.db.find({"age": {"$gte": 77}})
         assert len(docs) == 2
@@ -167,6 +179,10 @@ class BasicTextTests(mango.UserDocsTextTests):
         docs = self.db.find({"age": {"$gte": 80}})
         assert len(docs) == 0
 
+        docs = self.db.find({"company": {"$gte": "Zialactic"}})
+        assert len(docs) == 1
+        assert docs[0]["company"] == "Zialactic"
+
     def test_and(self):
         docs = self.db.find({"age": 22, "manager": True})
         assert len(docs) == 1


[4/5] couchdb-mango git commit: Pass supervisor's children to couch_epi

Posted by to...@apache.org.
Pass supervisor's children to couch_epi


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

Branch: refs/heads/2816-malformed-docs
Commit: 46b58a3c53bc07db8b841fd55dc9fb32c1b6bb89
Parents: 19184f3
Author: ILYA Khlopotov <ii...@ca.ibm.com>
Authored: Tue Sep 29 13:05:25 2015 -0700
Committer: ILYA Khlopotov <ii...@ca.ibm.com>
Committed: Tue Sep 29 13:05:25 2015 -0700

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


http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/46b58a3c/src/mango_sup.erl
----------------------------------------------------------------------
diff --git a/src/mango_sup.erl b/src/mango_sup.erl
index e7f014b..b0dedf1 100644
--- a/src/mango_sup.erl
+++ b/src/mango_sup.erl
@@ -21,4 +21,4 @@ start_link(Args) ->
     supervisor:start_link({local,?MODULE}, ?MODULE, Args).
 
 init([]) ->
-    {ok, {{one_for_one, 3, 10}, couch_epi:register_service(mango_epi)}}.
+    {ok, {{one_for_one, 3, 10}, couch_epi:register_service(mango_epi, [])}}.


[5/5] couchdb-mango git commit: Handle malformed manual design docs.

Posted by to...@apache.org.
Handle malformed manual design docs.

We separate index validation into three phases. The first phase is
index creation via our _index api. This validation piece will throw
an error for invalid index definitions. The second phase is during
the indexing of documents. If an index definition is not valid, we
will not use the definition to index documents. We silently log the
error. Finally, during the query phase, design documents are again
validated to ensure correct indexes are used. Again, we log an error
but silently ignore invalid index definitions. Our validation will
integrate into a consolidated validation of all indexers.

COUCHDB-2816


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

Branch: refs/heads/2816-malformed-docs
Commit: 87020c2202e892cc79549d90440d405f3efc7246
Parents: 46b58a3
Author: Tony Sun <to...@cloudant.com>
Authored: Wed Sep 16 16:42:47 2015 -0700
Committer: Tony Sun <to...@cloudant.com>
Committed: Mon Oct 5 12:44:58 2015 -0700

----------------------------------------------------------------------
 src/mango_httpd.erl             |  2 +-
 src/mango_idx.erl               |  6 +--
 src/mango_idx_text.erl          | 42 ++++++++++++++++-----
 src/mango_idx_view.erl          | 46 ++++++++++++++++-------
 src/mango_native_proc.erl       | 38 ++++++++++++++++++-
 test/05-index-selection-test.py | 71 ++++++++++++++++++++++++++++++++++++
 6 files changed, 176 insertions(+), 29 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/87020c22/src/mango_httpd.erl
----------------------------------------------------------------------
diff --git a/src/mango_httpd.erl b/src/mango_httpd.erl
index 8ac3d3c..ef83bda 100644
--- a/src/mango_httpd.erl
+++ b/src/mango_httpd.erl
@@ -83,7 +83,7 @@ handle_index_req(#httpd{method='GET', path_parts=[_, _]}=Req, Db) ->
 handle_index_req(#httpd{method='POST', path_parts=[_, _]}=Req, Db) ->
     {ok, Opts} = mango_opts:validate_idx_create(chttpd:json_body_obj(Req)),
     {ok, Idx0} = mango_idx:new(Db, Opts),
-    {ok, Idx} = mango_idx:validate(Idx0),
+    {ok, Idx} = mango_idx:validate_new(Idx0),
     {ok, DDoc} = mango_util:load_ddoc(Db, mango_idx:ddoc(Idx)),
     Id = Idx#idx.ddoc,
     Name = Idx#idx.name,

http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/87020c22/src/mango_idx.erl
----------------------------------------------------------------------
diff --git a/src/mango_idx.erl b/src/mango_idx.erl
index 867cbef..377af91 100644
--- a/src/mango_idx.erl
+++ b/src/mango_idx.erl
@@ -23,7 +23,7 @@
     for_sort/2,
 
     new/2,
-    validate/1,
+    validate_new/1,
     add/2,
     remove/2,
     from_ddoc/2,
@@ -114,9 +114,9 @@ new(Db, Opts) ->
     }}.
 
 
-validate(Idx) ->
+validate_new(Idx) ->
     Mod = idx_mod(Idx),
-    Mod:validate(Idx).
+    Mod:validate_new(Idx).
 
 
 add(DDoc, Idx) ->

http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/87020c22/src/mango_idx_text.erl
----------------------------------------------------------------------
diff --git a/src/mango_idx_text.erl b/src/mango_idx_text.erl
index 321889a..fcd2939 100644
--- a/src/mango_idx_text.erl
+++ b/src/mango_idx_text.erl
@@ -14,8 +14,9 @@
 
 
 -export([
-    validate/1,
+    validate_new/1,
     validate_fields/1,
+    validate_index_def/1,
     add/2,
     remove/2,
     from_ddoc/1,
@@ -31,11 +32,15 @@
 -include("mango_idx.hrl").
 
 
-validate(#idx{}=Idx) ->
+validate_new(#idx{}=Idx) ->
     {ok, Def} = do_validate(Idx#idx.def),
     {ok, Idx#idx{def=Def}}.
 
 
+validate_index_def(IndexInfo) ->
+    do_validate(IndexInfo).
+
+
 add(#doc{body={Props0}}=DDoc, Idx) ->
     Texts1 = case proplists:get_value(<<"indexes">>, Props0) of
         {Texts0} -> Texts0;
@@ -72,14 +77,17 @@ from_ddoc({Props}) ->
     case lists:keyfind(<<"indexes">>, 1, Props) of
         {<<"indexes">>, {Texts}} when is_list(Texts) ->
             lists:flatmap(fun({Name, {VProps}}) ->
-                Def = proplists:get_value(<<"index">>, VProps),
-                I = #idx{
-                    type = <<"text">>,
-                    name = Name,
-                    def = Def
-                },
-                % TODO: Validate the index definition
-                [I]
+                case validate_ddoc(VProps) of
+                    invalid_ddoc ->
+                        [];
+                    Def ->
+                        I = #idx{
+                        type = <<"text">>,
+                        name = Name,
+                        def = Def
+                        },
+                        [I]
+                end
             end, Texts);
         _ ->
             []
@@ -165,6 +173,8 @@ validate_field_type(<<"boolean">>) ->
     <<"boolean">>.
 
 
+validate_fields(<<"all_fields">>) ->
+    {ok, all_fields};
 validate_fields(Fields) ->
     try fields_to_json(Fields) of
         _ ->
@@ -174,6 +184,18 @@ validate_fields(Fields) ->
     end.
 
 
+validate_ddoc(VProps) ->
+    try
+        Def = proplists:get_value(<<"index">>, VProps),
+        validate_index_def(Def),
+        Def
+    catch Error:Reason ->
+        couch_log:error("Invalid Index Def ~p: Error. ~p, Reason: ~p",
+            [VProps, Error, Reason]),
+        invalid_ddoc
+    end.
+
+
 opts() ->
     [
         {<<"default_analyzer">>, [

http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/87020c22/src/mango_idx_view.erl
----------------------------------------------------------------------
diff --git a/src/mango_idx_view.erl b/src/mango_idx_view.erl
index cc5bcb3..0cc713f 100644
--- a/src/mango_idx_view.erl
+++ b/src/mango_idx_view.erl
@@ -14,7 +14,8 @@
 
 
 -export([
-    validate/1,
+    validate_new/1,
+    validate_index_def/1,
     add/2,
     remove/2,
     from_ddoc/1,
@@ -35,11 +36,15 @@
 -include("mango_idx.hrl").
 
 
-validate(#idx{}=Idx) ->
+validate_new(#idx{}=Idx) ->
     {ok, Def} = do_validate(Idx#idx.def),
     {ok, Idx#idx{def=Def}}.
 
 
+validate_index_def(Def) ->
+    def_to_json(Def).
+
+
 add(#doc{body={Props0}}=DDoc, Idx) ->
     Views1 = case proplists:get_value(<<"views">>, Props0) of
         {Views0} -> Views0;
@@ -75,17 +80,18 @@ from_ddoc({Props}) ->
     case lists:keyfind(<<"views">>, 1, Props) of
         {<<"views">>, {Views}} when is_list(Views) ->
             lists:flatmap(fun({Name, {VProps}}) ->
-                Def = proplists:get_value(<<"map">>, VProps),
-                {Opts0} = proplists:get_value(<<"options">>, VProps),
-                Opts = lists:keydelete(<<"sort">>, 1, Opts0),
-                I = #idx{
-                    type = <<"json">>,
-                    name = Name,
-                    def = Def,
-                    opts = Opts
-                },
-                % TODO: Validate the index definition
-                [I]
+                case validate_ddoc(VProps) of
+                    invalid_view ->
+                        [];
+                    {Def, Opts} ->
+                        I = #idx{
+                        type = <<"json">>,
+                        name = Name,
+                        def = Def,
+                        opts = Opts
+                        },
+                        [I]
+                end
             end, Views);
         _ ->
             []
@@ -204,6 +210,20 @@ make_view(Idx) ->
     {Idx#idx.name, View}.
 
 
+validate_ddoc(VProps) ->
+    try
+        Def = proplists:get_value(<<"map">>, VProps),
+        validate_index_def(Def),
+        {Opts0} = proplists:get_value(<<"options">>, VProps),
+        Opts = lists:keydelete(<<"sort">>, 1, Opts0),
+        {Def, Opts}
+    catch Error:Reason ->
+        couch_log:error("Invalid Index Def ~p. Error: ~p, Reason: ~p",
+            [VProps, Error, Reason]),
+        invalid_view
+    end.
+
+
 % This function returns a list of indexes that
 % can be used to restrict this query. This works by
 % searching the selector looking for field names that

http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/87020c22/src/mango_native_proc.erl
----------------------------------------------------------------------
diff --git a/src/mango_native_proc.erl b/src/mango_native_proc.erl
index 9481ca4..822d173 100644
--- a/src/mango_native_proc.erl
+++ b/src/mango_native_proc.erl
@@ -14,6 +14,9 @@
 -behavior(gen_server).
 
 
+-include("mango_idx.hrl").
+
+
 -export([
     start_link/0,
     set_timeout/2,
@@ -72,7 +75,13 @@ handle_call({prompt, [<<"reset">>, _QueryConfig]}, _From, St) ->
     {reply, true, St#st{indexes=[]}};
 
 handle_call({prompt, [<<"add_fun">>, IndexInfo]}, _From, St) ->
-    Indexes = St#st.indexes ++ [IndexInfo],
+    Indexes = case validate_index_info(IndexInfo) of
+        true ->
+            St#st.indexes ++ [IndexInfo];
+        false ->
+            couch_log:error("No Valid Indexes For: ~p", [IndexInfo]),
+            St#st.indexes
+    end,
     NewSt = St#st{indexes = Indexes},
     {reply, true, NewSt};
 
@@ -86,7 +95,14 @@ handle_call({prompt, [<<"rereduce">>, _, _]}, _From, St) ->
     {reply, null, St};
 
 handle_call({prompt, [<<"index_doc">>, Doc]}, _From, St) ->
-    {reply, index_doc(St, mango_json:to_binary(Doc)), St};
+    Vals = case index_doc(St, mango_json:to_binary(Doc)) of
+        [] ->
+            [[]];
+        Else ->
+            Else
+    end,
+    {reply, Vals, St};
+
 
 handle_call(Msg, _From, St) ->
     {stop, {invalid_call, Msg}, {invalid_call, Msg}, St}.
@@ -296,3 +312,21 @@ make_text_field_name([P | Rest], Type) ->
     Parts = lists:reverse(Rest, [iolist_to_binary([P, ":", Type])]),
     Escaped = [mango_util:lucene_escape_field(N) || N <- Parts],
     iolist_to_binary(mango_util:join(".", Escaped)).
+
+
+validate_index_info(IndexInfo) ->
+    IdxTypes = case module_loaded(dreyfus_index) of
+        true ->
+            [mango_idx_view, mango_idx_text];
+        false ->
+            [mango_idx_view]
+    end,
+    Results = lists:foldl(fun(IdxType, Results0) ->
+        try
+            IdxType:validate_index_def(IndexInfo),
+            [valid_index | Results0]
+        catch _:_ ->
+            [invalid_index | Results0]
+        end
+    end, [], IdxTypes),
+    lists:member(valid_index, Results).
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/87020c22/test/05-index-selection-test.py
----------------------------------------------------------------------
diff --git a/test/05-index-selection-test.py b/test/05-index-selection-test.py
index eecaf17..3652bc4 100644
--- a/test/05-index-selection-test.py
+++ b/test/05-index-selection-test.py
@@ -74,6 +74,77 @@ class IndexSelectionTests(mango.UserDocsTests):
             }, use_index=ddocid, explain=True)
         assert resp["index"]["ddoc"] == ddocid
 
+    # Silently log error and use good index def in ddoc
+    def test_manual_bad_view_idx01(self):
+        design_doc = {
+            "_id": "_design/bad_view_index",
+            "language": "query",
+            "views": {
+                "queryidx1": {
+                    "map": {
+                        "fields": {
+                            "age": "asc"
+                        }
+                    },
+                    "reduce": "_count",
+                    "options": {
+                        "def": {
+                            "fields": [
+                                {
+                                    "age": "asc"
+                                }
+                            ]
+                        },
+                        "w": 2
+                    }
+                }
+            },
+            "views" : {
+                "views001" : {
+                "map" : "function(employee){if(employee.training)"
+                    + "{emit(employee.number, employee.training);}}"
+                }
+            }
+        }
+        self.db.save_doc(design_doc)
+        docs= self.db.find({"age" : 48})
+        assert len(docs) == 1
+        assert docs[0]["name"]["first"] == "Stephanie"
+        assert docs[0]["age"] == 48
+
+    @unittest.skipUnless(mango.has_text_service(), "requires text service")
+    def test_manual_bad_text_idx(self):
+        design_doc = {
+            "_id": "_design/bad_text_index",
+            "language": "query",
+            "indexes": {
+                    "text_index": {
+                        "default_analyzer": "keyword",
+                        "default_field": {},
+                        "selector": {},
+                        "fields": "all_fields",
+                        "analyzer": {
+                        "name": "perfield",
+                        "default": "keyword",
+                        "fields": {
+                            "$default": "standard"
+                        }
+                    }
+                }
+            },
+            "indexes": {
+                "st_index": {
+                    "analyzer": "standard",
+                    "index": "function(doc){\n index(\"st_index\", doc.geometry);\n}"
+                }
+            }
+        }
+        self.db.save_doc(design_doc)
+        docs= self.db.find({"age" : 48})
+        assert len(docs) == 1
+        assert docs[0]["name"]["first"] == "Stephanie"
+        assert docs[0]["age"] == 48
+
 
 @unittest.skipUnless(mango.has_text_service(), "requires text service")
 class MultiTextIndexSelectionTests(mango.UserDocsTests):


[2/5] couchdb-mango git commit: Fix crypto deprecations

Posted by to...@apache.org.
Fix crypto deprecations

COUCHDB-2825


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

Branch: refs/heads/2816-malformed-docs
Commit: 9eb60e78ca2d8abb42d40324470dd54d37a84746
Parents: bb595d0
Author: Robert Newson <rn...@apache.org>
Authored: Wed Sep 23 19:38:33 2015 +0100
Committer: Robert Newson <rn...@apache.org>
Committed: Wed Sep 23 19:38:33 2015 +0100

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


http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/9eb60e78/src/mango_idx.erl
----------------------------------------------------------------------
diff --git a/src/mango_idx.erl b/src/mango_idx.erl
index 56b7fc2..867cbef 100644
--- a/src/mango_idx.erl
+++ b/src/mango_idx.erl
@@ -325,7 +325,7 @@ get_idx_name(Idx, Opts) ->
 gen_name(Idx, Opts0) ->
     Opts = lists:usort(Opts0),
     TermBin = term_to_binary({Idx, Opts}),
-    Sha = crypto:sha(TermBin),
+    Sha = couch_crypto:hash(sha, TermBin),
     mango_util:enc_hex(Sha).
 
 


[3/5] couchdb-mango git commit: Update to new couch_epi API

Posted by to...@apache.org.
Update to new couch_epi API


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

Branch: refs/heads/2816-malformed-docs
Commit: 19184f3c28cc23b880901b94fe7545428628bfd0
Parents: 9eb60e7
Author: ILYA Khlopotov <ii...@ca.ibm.com>
Authored: Mon Sep 28 09:53:20 2015 -0700
Committer: ILYA Khlopotov <ii...@ca.ibm.com>
Committed: Mon Sep 28 09:53:20 2015 -0700

----------------------------------------------------------------------
 src/mango_epi.erl | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
 src/mango_sup.erl |  4 +---
 2 files changed, 49 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/19184f3c/src/mango_epi.erl
----------------------------------------------------------------------
diff --git a/src/mango_epi.erl b/src/mango_epi.erl
new file mode 100644
index 0000000..1fcd05b
--- /dev/null
+++ b/src/mango_epi.erl
@@ -0,0 +1,48 @@
+% 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(mango_epi).
+
+-behaviour(couch_epi_plugin).
+
+-export([
+    app/0,
+    providers/0,
+    services/0,
+    data_subscriptions/0,
+    data_providers/0,
+    processes/0,
+    notify/3
+]).
+
+app() ->
+    mango.
+
+providers() ->
+    [
+         {chttpd_handlers, mango_httpd_handlers}
+    ].
+
+services() ->
+    [].
+
+data_subscriptions() ->
+    [].
+
+data_providers() ->
+    [].
+
+processes() ->
+    [].
+
+notify(_Key, _Old, _New) ->
+    ok.

http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/19184f3c/src/mango_sup.erl
----------------------------------------------------------------------
diff --git a/src/mango_sup.erl b/src/mango_sup.erl
index 7f4cd10..e7f014b 100644
--- a/src/mango_sup.erl
+++ b/src/mango_sup.erl
@@ -21,6 +21,4 @@ start_link(Args) ->
     supervisor:start_link({local,?MODULE}, ?MODULE, Args).
 
 init([]) ->
-    {ok, {{one_for_one, 3, 10}, [
-        chttpd_handlers:provider(mango, mango_httpd_handlers)
-    ]}}.
+    {ok, {{one_for_one, 3, 10}, couch_epi:register_service(mango_epi)}}.