diff options
author | Paul J. Davis <paul.joseph.davis@gmail.com> | 2018-10-23 14:18:35 -0500 |
---|---|---|
committer | Paul J. Davis <paul.joseph.davis@gmail.com> | 2019-01-18 13:03:28 -0600 |
commit | 6edb9a54b7111fdb0a1713d1af2268271e27d02f (patch) | |
tree | 328a60e22133b03d66de953e2d7aa73ee3069fd3 /src/couch | |
parent | 25ac408362e9ffd565f1edf360f3bd7e6a92a7eb (diff) | |
download | couchdb-6edb9a54b7111fdb0a1713d1af2268271e27d02f.tar.gz |
Implement `couch_db:get_partition_info/2`
This feature allows us to fetch statistics for a given partition key
which will allow for users to find bloated partitions and such forth.
Co-authored-by: Garren Smith <garren.smith@gmail.com>
Co-authored-by: Robert Newson <rnewson@apache.org>
Diffstat (limited to 'src/couch')
-rw-r--r-- | src/couch/src/couch_bt_engine.erl | 43 | ||||
-rw-r--r-- | src/couch/src/couch_db.erl | 8 | ||||
-rw-r--r-- | src/couch/src/couch_db_engine.erl | 24 | ||||
-rw-r--r-- | src/couch/src/couch_partition.erl | 11 |
4 files changed, 86 insertions, 0 deletions
diff --git a/src/couch/src/couch_bt_engine.erl b/src/couch/src/couch_bt_engine.erl index 946b74d0c..7b33c4203 100644 --- a/src/couch/src/couch_bt_engine.erl +++ b/src/couch/src/couch_bt_engine.erl @@ -42,6 +42,7 @@ get_security/1, get_props/1, get_size_info/1, + get_partition_info/2, get_update_seq/1, get_uuid/1, @@ -277,6 +278,48 @@ get_size_info(#st{} = St) -> ]. +partition_size_cb(traverse, Key, {DC, DDC, Sizes}, {Partition, DCAcc, DDCAcc, SizesAcc}) -> + case couch_partition:is_member(Key, Partition) of + true -> + {skip, {Partition, DC + DCAcc, DDC + DDCAcc, reduce_sizes(Sizes, SizesAcc)}}; + false -> + {ok, {Partition, DCAcc, DDCAcc, SizesAcc}} + end; + +partition_size_cb(visit, FDI, _PrevReds, {Partition, DCAcc, DDCAcc, Acc}) -> + InPartition = couch_partition:is_member(FDI#full_doc_info.id, Partition), + Deleted = FDI#full_doc_info.deleted, + case {InPartition, Deleted} of + {true, true} -> + {ok, {Partition, DCAcc, DDCAcc + 1, + reduce_sizes(FDI#full_doc_info.sizes, Acc)}}; + {true, false} -> + {ok, {Partition, DCAcc + 1, DDCAcc, + reduce_sizes(FDI#full_doc_info.sizes, Acc)}}; + {false, _} -> + {ok, {Partition, DCAcc, DDCAcc, Acc}} + end. + + +get_partition_info(#st{} = St, Partition) -> + StartKey = couch_partition:start_key(Partition), + EndKey = couch_partition:end_key(Partition), + Fun = fun partition_size_cb/4, + InitAcc = {Partition, 0, 0, #size_info{}}, + Options = [{start_key, StartKey}, {end_key, EndKey}], + {ok, _, OutAcc} = couch_btree:fold(St#st.id_tree, Fun, InitAcc, Options), + {Partition, DocCount, DocDelCount, SizeInfo} = OutAcc, + [ + {partition, Partition}, + {doc_count, DocCount}, + {doc_del_count, DocDelCount}, + {sizes, [ + {active, SizeInfo#size_info.active}, + {external, SizeInfo#size_info.external} + ]} + ]. + + get_security(#st{header = Header} = St) -> case couch_bt_engine_header:get(Header, security_ptr) of undefined -> diff --git a/src/couch/src/couch_db.erl b/src/couch/src/couch_db.erl index 2c6f41bf7..74f4a099d 100644 --- a/src/couch/src/couch_db.erl +++ b/src/couch/src/couch_db.erl @@ -38,6 +38,7 @@ get_compacted_seq/1, get_compactor_pid/1, get_db_info/1, + get_partition_info/2, get_del_doc_count/1, get_doc_count/1, get_epochs/1, @@ -633,6 +634,13 @@ get_db_info(Db) -> ], {ok, InfoList}. +get_partition_info(#db{} = Db, Partition) when is_binary(Partition) -> + Info = couch_db_engine:get_partition_info(Db, Partition), + {ok, Info}; +get_partition_info(_Db, _Partition) -> + throw({bad_request, <<"`partition` is not valid">>}). + + get_design_doc(#db{name = <<"shards/", _/binary>> = ShardDbName}, DDocId0) -> DDocId = couch_util:normalize_ddoc_id(DDocId0), DbName = mem3:dbname(ShardDbName), diff --git a/src/couch/src/couch_db_engine.erl b/src/couch/src/couch_db_engine.erl index 806d352cb..91d35b0c7 100644 --- a/src/couch/src/couch_db_engine.erl +++ b/src/couch/src/couch_db_engine.erl @@ -44,6 +44,12 @@ -type purge_info() :: {purge_seq(), uuid(), docid(), revs()}. -type epochs() :: [{Node::atom(), UpdateSeq::non_neg_integer()}]. -type size_info() :: [{Name::atom(), Size::non_neg_integer()}]. +-type partition_info() :: [ + {partition, Partition::binary()} | + {doc_count, DocCount::non_neg_integer()} | + {doc_del_count, DocDelCount::non_neg_integer()} | + {sizes, size_info()} +]. -type write_stream_options() :: [ {buffer_size, Size::pos_integer()} | @@ -263,6 +269,18 @@ -callback get_size_info(DbHandle::db_handle()) -> SizeInfo::size_info(). +% This returns the information for the given partition. +% It should just be a list of {Name::atom(), Size::non_neg_integer()} +% It returns the partition name, doc count, deleted doc count and two sizes: +% +% active - Theoretical minimum number of bytes to store this partition on disk +% +% external - Number of bytes that would be required to represent the +% contents of this partition outside of the database +-callback get_partition_info(DbHandle::db_handle(), Partition::binary()) -> + partition_info(). + + % The current update sequence of the database. The update % sequence should be incrememnted for every revision added to % the database. @@ -685,6 +703,7 @@ get_security/1, get_props/1, get_size_info/1, + get_partition_info/2, get_update_seq/1, get_uuid/1, @@ -861,6 +880,11 @@ get_size_info(#db{} = Db) -> Engine:get_size_info(EngineState). +get_partition_info(#db{} = Db, Partition) -> + #db{engine = {Engine, EngineState}} = Db, + Engine:get_partition_info(EngineState, Partition). + + get_update_seq(#db{} = Db) -> #db{engine = {Engine, EngineState}} = Db, Engine:get_update_seq(EngineState). diff --git a/src/couch/src/couch_partition.erl b/src/couch/src/couch_partition.erl index 783921f0a..9ff77a0ff 100644 --- a/src/couch/src/couch_partition.erl +++ b/src/couch/src/couch_partition.erl @@ -18,6 +18,9 @@ from_docid/1, is_member/2, + start_key/1, + end_key/1, + validate_dbname/2, validate_docid/1, validate_partition/1, @@ -59,6 +62,14 @@ is_member(DocId, Partition) -> end. +start_key(Partition) -> + <<Partition/binary, ":">>. + + +end_key(Partition) -> + <<Partition/binary, ";">>. + + validate_dbname(DbName, Options) when is_list(DbName) -> validate_dbname(?l2b(DbName), Options); validate_dbname(DbName, Options) when is_binary(DbName) -> |