summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGarren Smith <garren.smith@gmail.com>2018-10-23 16:35:29 +0200
committergarren smith <garren.smith@gmail.com>2018-11-21 08:31:17 +0200
commit854f3d9fcbd8db91ab208e27038c252d91841fcf (patch)
treef097a000b416add9b116758d45fb5a59c1eaa03b
parent1008d9710145d7f5742cd0a02dfc7272ed473849 (diff)
downloadcouchdb-854f3d9fcbd8db91ab208e27038c252d91841fcf.tar.gz
This adds in downgrade code for Database partitions work. We add an
extra field in the header.
-rw-r--r--src/couch/src/couch_bt_engine_header.erl53
-rw-r--r--src/couch/test/couch_bt_engine_partition_downgrade_tests.erl86
-rw-r--r--src/couch/test/fixtures/db_non_partitioned.couchbin0 -> 12479 bytes
3 files changed, 139 insertions, 0 deletions
diff --git a/src/couch/src/couch_bt_engine_header.erl b/src/couch/src/couch_bt_engine_header.erl
index 9c8e7adb3..619264a0d 100644
--- a/src/couch/src/couch_bt_engine_header.erl
+++ b/src/couch/src/couch_bt_engine_header.erl
@@ -26,6 +26,7 @@
-export([
disk_version/1,
+ latest_disk_version/0,
update_seq/1,
id_tree_state/1,
seq_tree_state/1,
@@ -72,6 +73,9 @@
}).
+-define(PARTITION_DISK_VERSION, 8).
+
+
new() ->
#db_header{
uuid = couch_uuids:random(),
@@ -99,6 +103,7 @@ is_header(Header) ->
upgrade(Header) ->
Funs = [
+ fun downgrade_partition_header/1,
fun upgrade_tuple/1,
fun upgrade_disk_version/1,
fun upgrade_uuid/1,
@@ -136,6 +141,10 @@ disk_version(Header) ->
get_field(Header, disk_version).
+latest_disk_version() ->
+ ?LATEST_DISK_VERSION.
+
+
update_seq(Header) ->
get_field(Header, update_seq).
@@ -210,6 +219,50 @@ indexes() ->
lists:zip(Fields, Indexes).
+downgrade_partition_header(Header) ->
+ DiskVersion = disk_version(Header),
+ Latest = latest_disk_version(),
+ case DiskVersion of
+ N when N =< Latest ->
+ Header;
+ ?PARTITION_DISK_VERSION ->
+ {
+ db_header,
+ _DiskVer,
+ UpSeq,
+ _Unused,
+ IdTreeState,
+ SeqTreeState,
+ LocalTreeState,
+ PurgeTreeState,
+ PurgeSeqTreeState,
+ SecurityPtr,
+ RevsLimit,
+ Uuid,
+ Epochs,
+ CompactedSeq,
+ PurgeInfosLimit,
+ _PropsPtr
+ } = Header,
+
+ NewHeader = new(),
+ set(NewHeader, [
+ {update_seq, UpSeq},
+ {id_tree_state, IdTreeState},
+ {seq_tree_state, SeqTreeState},
+ {local_tree_state, LocalTreeState},
+ {purge_tree_state, PurgeTreeState},
+ {purge_seq_tree_state, PurgeSeqTreeState},
+ {security_ptr, SecurityPtr},
+ {revs_limit, RevsLimit},
+ {uuid, Uuid},
+ {epochs, Epochs},
+ {compacted_seq, CompactedSeq},
+ {purge_infos_limit, PurgeInfosLimit}
+ ])
+ end.
+
+
upgrade_tuple(Old) when is_record(Old, db_header) ->
Old;
upgrade_tuple(Old) when is_tuple(Old) ->
diff --git a/src/couch/test/couch_bt_engine_partition_downgrade_tests.erl b/src/couch/test/couch_bt_engine_partition_downgrade_tests.erl
new file mode 100644
index 000000000..f0839a411
--- /dev/null
+++ b/src/couch/test/couch_bt_engine_partition_downgrade_tests.erl
@@ -0,0 +1,86 @@
+% 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_bt_engine_partition_downgrade_tests).
+
+-include_lib("couch/include/couch_eunit.hrl").
+-include_lib("couch/include/couch_db.hrl").
+
+
+setup() ->
+ Ctx = test_util:start_couch(),
+ DbDir = config:get("couchdb", "database_dir"),
+ DbFileNames = [
+ "db_non_partitioned.couch"
+ ],
+ NewPaths = lists:map(fun(DbFileName) ->
+ OldDbFilePath = filename:join([?FIXTURESDIR, DbFileName]),
+ NewDbFilePath = filename:join([DbDir, DbFileName]),
+ ok = filelib:ensure_dir(NewDbFilePath),
+ file:delete(NewDbFilePath),
+ {ok, _} = file:copy(OldDbFilePath, NewDbFilePath),
+ NewDbFilePath
+ end, DbFileNames),
+ {Ctx, NewPaths}.
+
+
+teardown({Ctx, Paths}) ->
+ test_util:stop_couch(Ctx),
+ lists:foreach(fun(Path) ->
+ file:delete(Path)
+ end, Paths).
+
+
+downgrade_test_() ->
+ {
+ "Couch Bt Engine partition downgrade tests",
+ {
+ setup,
+ fun setup/0,
+ fun teardown/1,
+ [
+ t_downgrade_non_partitioned_db()
+ ]
+ }
+ }.
+
+
+t_downgrade_non_partitioned_db() ->
+ ?_test(begin
+ % There are 13 documents in the fixture with 1 conflicted
+ DbName = <<"db_non_partitioned">>,
+ ?assertEqual(8, get_disk_version_from_header(DbName)),
+
+ {ok, _} = save_doc(DbName, {[{<<"_id">>, <<"doc4">>}, {<<"v">>, 1}]}),
+ {ok, _} = save_doc(DbName, {[{<<"_id">>, <<"doc5">>}, {<<"v">>, 2}]}),
+
+ couch_util:with_db(DbName, fun(Db) ->
+ ?assertEqual(7, couch_db_engine:get_disk_version(Db))
+ end)
+ end).
+
+
+get_disk_version_from_header(DbFileName) ->
+ DbDir = config:get("couchdb", "database_dir"),
+ DbFilePath = filename:join([DbDir, ?l2b(?b2l(DbFileName) ++ ".couch")]),
+ {ok, Fd} = couch_file:open(DbFilePath, []),
+ {ok, Header} = couch_file:read_header(Fd),
+ DiskVerison = couch_bt_engine_header:disk_version(Header),
+ couch_file:close(Fd),
+ DiskVerison.
+
+
+save_doc(DbName, Json) ->
+ Doc = couch_doc:from_json_obj(Json),
+ couch_util:with_db(DbName, fun(Db) ->
+ couch_db:update_doc(Db, Doc, [])
+ end).
diff --git a/src/couch/test/fixtures/db_non_partitioned.couch b/src/couch/test/fixtures/db_non_partitioned.couch
new file mode 100644
index 000000000..327d9bb5d
--- /dev/null
+++ b/src/couch/test/fixtures/db_non_partitioned.couch
Binary files differ