You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by rn...@apache.org on 2014/08/01 11:04:59 UTC

[6/9] git commit: Delete old security docs when we set security

Delete old security docs when we set security

When we set security, we now also call out to cleanup old docs, which
will find all docs with same meta group id, where a meta group is a
user/database/type name, or more simply, a meta id with the suffix
removed. We use the meta group to fetch all previous security docs and
then delete the non current docs.

Note that the winning security doc may not in fact have the newest
suffix, as we could get into a situation with conflicts where the
winning rev is not the newest, so instead of sorting by suffix and
deleting everything but the newest, we instead delete everything
besides the meta id we know is the winner. We know the winning meta id
because in the set_security update we fetch the current known winning
id and pass that along to cleanup_old_docs/1.

The meta id format has been changed slightly, to append the suffix at
the end of the user/database/type group name, so that we can just chop
off the suffix and have the group.

Also, this moves the security_meta_id function into the
cassim_metadata_cache module. The motivation for this is that we're
using the suffix now to distinguish between different database
versions, which is general to all potential metadata types, not just
security, and so we want to keep the id definitions local to the cache
so we can more easily ensure all future id formats end in the suffix.

BugzId: 29571


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

Branch: refs/heads/windsor-merge
Commit: 1fe57773c2184fe6037a82239f18b133270eaf65
Parents: 02a5c7c
Author: Russell Branca <ch...@gmail.com>
Authored: Thu May 1 11:11:10 2014 -0700
Committer: Robert Newson <rn...@apache.org>
Committed: Wed Jul 30 18:18:00 2014 +0100

----------------------------------------------------------------------
 src/cassim_metadata_cache.erl | 53 +++++++++++++++++++++++++++++++++++++-
 src/cassim_security.erl       | 13 +++-------
 2 files changed, 56 insertions(+), 10 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-cassim/blob/1fe57773/src/cassim_metadata_cache.erl
----------------------------------------------------------------------
diff --git a/src/cassim_metadata_cache.erl b/src/cassim_metadata_cache.erl
index b0246d8..ea8d25c 100644
--- a/src/cassim_metadata_cache.erl
+++ b/src/cassim_metadata_cache.erl
@@ -34,7 +34,12 @@
     load_meta/2,
     load_meta/3,
     metadata_db/0,
-    metadata_db_exists/0
+    metadata_db_exists/0,
+    cleanup_old_docs/1
+]).
+
+-export([
+    security_meta_id/1
 ]).
 
 
@@ -65,6 +70,11 @@ metadata_db_exists() ->
     end.
 
 
+security_meta_id(DbName) ->
+    Suffix = list_to_binary(mem3:shard_suffix(DbName)),
+    <<DbName/binary, "/_security", Suffix/binary>>.
+
+
 start_link() ->
     gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
 
@@ -212,3 +222,44 @@ fetch_cached_meta(MetaId) ->
             couch_log:notice("cache miss on metadata ~s", [MetaId]),
             undefined
     end.
+
+
+cleanup_old_docs(MetaId) ->
+    MetaGroupId = filename:rootname(binary_to_list(MetaId)),
+    {ok, {_MetaId, Docs}} = fabric:all_docs(
+        metadata_db(),
+        fun cleanup_old_docs_callback/2,
+        {MetaId, []},
+        [
+            {start_key, list_to_binary(MetaGroupId)},
+            {end_key, list_to_binary(MetaGroupId ++ "Z")},
+            {include_docs, true}
+        ]
+    ),
+    {ok, _Revs} = delete_meta_docs(Docs),
+    ok.
+
+
+cleanup_old_docs_callback({total_and_offset, _Total, _Offset}, {MetaId, Acc}) ->
+    {ok, {MetaId, Acc}};
+cleanup_old_docs_callback({row, {Row}}, {MetaId, Acc}) ->
+    Id = couch_util:get_value(id, Row),
+    case MetaId == Id of
+        true ->
+            {ok, {MetaId, Acc}};
+        false ->
+            Doc = couch_doc:from_json_obj(couch_util:get_value(doc, Row)),
+            {ok, {MetaId, [Doc|Acc]}}
+    end;
+cleanup_old_docs_callback(complete, {MetaId, Acc}) ->
+    {ok, {MetaId, Acc}};
+cleanup_old_docs_callback({error, Reason}, {MetaId, Acc}) ->
+    couch_log:error("Unable clean up all old docs on ~p: ~p", [MetaId, Reason]),
+    {ok, {MetaId, Acc}}.
+
+
+delete_meta_docs(Docs0) ->
+    Docs = [D#doc{deleted=true, body={[]}} || D <- Docs0],
+    Options = [{user_ctx, #user_ctx{roles=[<<"_admin">>]}}],
+    DbName = metadata_db(),
+    fabric:update_docs(DbName, Docs, Options).

http://git-wip-us.apache.org/repos/asf/couchdb-cassim/blob/1fe57773/src/cassim_security.erl
----------------------------------------------------------------------
diff --git a/src/cassim_security.erl b/src/cassim_security.erl
index 6cf4c68..daa9cfb 100644
--- a/src/cassim_security.erl
+++ b/src/cassim_security.erl
@@ -28,7 +28,6 @@
 ]).
 
 -export([
-    security_meta_id/1,
     validate_security_doc/1
 ]).
 
@@ -40,11 +39,6 @@
 -define(ADMIN_CTX, {user_ctx, ?ADMIN_USER}).
 
 
-security_meta_id(DbName) ->
-    Suffix = list_to_binary(mem3:shard_suffix(DbName)),
-    <<DbName/binary, Suffix/binary, "/_security">>.
-
-
 get_security(DbName) ->
     get_security(DbName, [?ADMIN_CTX]).
 
@@ -66,7 +60,7 @@ get_security(DbName, Options) ->
 
 get_security_doc(DbName0) when is_binary(DbName0) ->
     DbName = mem3:dbname(DbName0),
-    MetaId = security_meta_id(DbName),
+    MetaId = cassim_metadata_cache:security_meta_id(DbName),
     case cassim_metadata_cache:load_meta(MetaId) of
         undefined ->
             SecProps = fabric:get_security(DbName),
@@ -85,7 +79,7 @@ set_security(#db{name=DbName0}=Db, #doc{body=SecProps}=SecDoc0, Options) ->
     case cassim_metadata_cache:metadata_db_exists() of
         true ->
             DbName = mem3:dbname(DbName0),
-            MetaId = security_meta_id(DbName),
+            MetaId = cassim_metadata_cache:security_meta_id(DbName),
             SecDoc = SecDoc0#doc{id=MetaId},
             UserCtx = couch_util:get_value(user_ctx, Options, #user_ctx{}),
             MetaDbName = cassim_metadata_cache:metadata_db(),
@@ -95,6 +89,7 @@ set_security(#db{name=DbName0}=Db, #doc{body=SecProps}=SecDoc0, Options) ->
             {Status, Etag, {Body0}} =
                 chttpd_db:update_doc(MetaDb, MetaId, SecDoc, Options),
             Body = {proplists:delete(<<"_id">>, Body0)},
+            ok = cassim_metadata_cache:cleanup_old_docs(MetaId),
             {Status, Etag, Body};
         false ->
             fabric:set_security(Db, SecProps, Options)
@@ -103,7 +98,7 @@ set_security(#db{name=DbName0}=Db, #doc{body=SecProps}=SecDoc0, Options) ->
 
 migrate_security_props(DbName0, {SecProps}) ->
     DbName = mem3:dbname(DbName0),
-    MetaId = security_meta_id(DbName),
+    MetaId = cassim_metadata_cache:security_meta_id(DbName),
     SecDoc = #doc{id=MetaId, body={SecProps}},
     MetaDbName = cassim_metadata_cache:metadata_db(),
     MetaDb = #db{name=MetaDbName, user_ctx=?ADMIN_USER},