diff options
author | jiangph <jiangph@cn.ibm.com> | 2018-09-19 17:33:16 +0800 |
---|---|---|
committer | jiangph <jiangph@cn.ibm.com> | 2018-09-19 21:55:04 +0800 |
commit | c4faf706a9bba87d89d3e056d7402878aa5d6341 (patch) | |
tree | 4c166d9a96e1495d45c25a8aeffa5c8e18fc0b07 | |
parent | b4bfc529efdba4b971cd8351dc1fa6b552089744 (diff) | |
download | couchdb-c4faf706a9bba87d89d3e056d7402878aa5d6341.tar.gz |
Add downgrade_purge_info function to downgrade databaseCOUCHDB-3226-pre-clustered-purge
COUCHDB-3226
-rw-r--r-- | src/couch/src/couch_bt_engine.erl | 74 |
1 files changed, 73 insertions, 1 deletions
diff --git a/src/couch/src/couch_bt_engine.erl b/src/couch/src/couch_bt_engine.erl index 6d858ed49..91119b4e6 100644 --- a/src/couch/src/couch_bt_engine.erl +++ b/src/couch/src/couch_bt_engine.erl @@ -787,7 +787,17 @@ init_state(FilePath, Fd, Header0, Options) -> Compression = couch_compress:get_compression_method(), - Header1 = couch_bt_engine_header:upgrade(Header0), + DiskV = couch_bt_engine_header:disk_version(Header0), + Header1 = case couch_bt_engine_header:latest(DiskV) of + undefined -> + % disk_version is higher that the latest version + % db must be the format of Clustered Purge, + % perform downgrade + downgrade_purge_info(Fd, Header0); + _ -> + couch_bt_engine_header:upgrade(Header0) + end, + Header2 = set_default_security_object(Fd, Header1, Compression, Options), Header = upgrade_purge_info(Fd, Header2), @@ -888,6 +898,68 @@ set_default_security_object(Fd, Header, Compression, Options) -> end. +% Rollback for clustered purge. It replaces PurgeTreeState and PurgeSeqTreeState +% with purged_docs disk pointer that stores only the last purge request +downgrade_purge_info(Fd, Header) -> + { + db_header, + _DiskVer, + UpSeq, + _Unused, + IdTreeState, + SeqTreeState, + LocalTreeState, + PurgeTreeState, + PurgeSeqTreeState, + SecurityPtr, + RevsLimit, + Uuid, + Epochs, + CompactedSeq, + _PDocsLimit + } = Header, + + {PSeq, PurgedDocsPtr} = case PurgeTreeState of + nil -> + {0, nil}; + PurgeSeqInOldVer when is_integer(PurgeSeqInOldVer)-> + {PurgeSeqInOldVer, nil}; + _ when is_tuple(PurgeTreeState) -> + {ok, PSTree} = couch_btree:open(PurgeSeqTreeState, Fd, [ + {split, fun ?MODULE:purge_seq_tree_split/1}, + {join, fun ?MODULE:purge_seq_tree_join/2}, + {reduce, fun ?MODULE:purge_tree_reduce/2} + ]), + + Fun = fun({PurgeSeq, _, _, _}, _Reds, _Acc) -> + {stop, PurgeSeq} + end, + {ok, _, PurgeSeq} = couch_btree:fold(PSTree, Fun, 0, [{dir, rev}]), + [{ok, {PurgeSeq, _UUID, Id, Revs}}] = couch_btree:lookup( + PSTree, [PurgeSeq]), + IdRevs = [{Id, Revs}], + Compression = couch_compress:get_compression_method(), + AppendOps = [{compression, Compression}], + {ok, Ptr, _} = couch_file:append_term(Fd, IdRevs, AppendOps), + {PurgeSeq, Ptr} + end, + + NewHeader = couch_bt_engine_header:new(), + couch_bt_engine_header:set(NewHeader, [ + {update_seq, UpSeq}, + {id_tree_state, IdTreeState}, + {seq_tree_state, SeqTreeState}, + {local_tree_state, LocalTreeState}, + {purge_seq, PSeq}, + {purged_docs, PurgedDocsPtr}, + {security_ptr, SecurityPtr}, + {revs_limit, RevsLimit}, + {uuid, Uuid}, + {epochs, Epochs}, + {compacted_seq, CompactedSeq} + ]). + + % This function is here, and not in couch_bt_engine_header % because it requires modifying file contents upgrade_purge_info(Fd, Header) -> |