Improved testing
Improve testing of Penciller to show startup and shutdown with push, merging and fetch
This commit is contained in:
parent
0d905639be
commit
edfe9e3bed
5 changed files with 193 additions and 23 deletions
|
@ -26,4 +26,8 @@
|
||||||
-record(inker_options,
|
-record(inker_options,
|
||||||
{cdb_max_size :: integer(),
|
{cdb_max_size :: integer(),
|
||||||
root_path :: string(),
|
root_path :: string(),
|
||||||
cdb_options :: #cdb_options{}}).
|
cdb_options :: #cdb_options{}}).
|
||||||
|
|
||||||
|
-record(penciller_options,
|
||||||
|
{root_path :: string(),
|
||||||
|
max_inmemory_tablesize :: integer()}).
|
|
@ -90,3 +90,77 @@
|
||||||
|
|
||||||
-module(leveled_bookie).
|
-module(leveled_bookie).
|
||||||
|
|
||||||
|
-behaviour(gen_server).
|
||||||
|
|
||||||
|
-include("../include/leveled.hrl").
|
||||||
|
|
||||||
|
-export([init/1,
|
||||||
|
handle_call/3,
|
||||||
|
handle_cast/2,
|
||||||
|
handle_info/2,
|
||||||
|
terminate/2,
|
||||||
|
code_change/3]).
|
||||||
|
|
||||||
|
-include_lib("eunit/include/eunit.hrl").
|
||||||
|
|
||||||
|
|
||||||
|
-record(state, {inker :: pid(),
|
||||||
|
penciller :: pid()}).
|
||||||
|
|
||||||
|
|
||||||
|
%%%============================================================================
|
||||||
|
%%% API
|
||||||
|
%%%============================================================================
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
%%%============================================================================
|
||||||
|
%%% gen_server callbacks
|
||||||
|
%%%============================================================================
|
||||||
|
|
||||||
|
init([Opts]) ->
|
||||||
|
{InkerOpts, PencillerOpts} = set_options(Opts),
|
||||||
|
{Inker, Penciller} = startup(InkerOpts, PencillerOpts),
|
||||||
|
{ok, #state{inker=Inker, penciller=Penciller}}.
|
||||||
|
|
||||||
|
|
||||||
|
handle_call(_, _From, State) ->
|
||||||
|
{reply, ok, State}.
|
||||||
|
|
||||||
|
handle_cast(_Msg, State) ->
|
||||||
|
{noreply, State}.
|
||||||
|
|
||||||
|
handle_info(_Info, State) ->
|
||||||
|
{noreply, State}.
|
||||||
|
|
||||||
|
terminate(_Reason, _State) ->
|
||||||
|
ok.
|
||||||
|
|
||||||
|
code_change(_OldVsn, State, _Extra) ->
|
||||||
|
{ok, State}.
|
||||||
|
|
||||||
|
|
||||||
|
%%%============================================================================
|
||||||
|
%%% Internal functions
|
||||||
|
%%%============================================================================
|
||||||
|
|
||||||
|
set_options(_Opts) ->
|
||||||
|
{#inker_options{}, #penciller_options{}}.
|
||||||
|
|
||||||
|
startup(InkerOpts, PencillerOpts) ->
|
||||||
|
{ok, Inker} = leveled_inker:ink_start(InkerOpts),
|
||||||
|
{ok, Penciller} = leveled_penciller:pcl_start(PencillerOpts),
|
||||||
|
LedgerSQN = leveled_penciller:pcl_getstartupsequencenumber(Penciller),
|
||||||
|
KeyChanges = leveled_inker:ink_fetchkeychangesfrom(Inker, LedgerSQN),
|
||||||
|
ok = leveled_penciller:pcl_pushmem(Penciller, KeyChanges),
|
||||||
|
{Inker, Penciller}.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
%%%============================================================================
|
||||||
|
%%% Test
|
||||||
|
%%%============================================================================
|
||||||
|
|
||||||
|
-ifdef(TEST).
|
||||||
|
|
||||||
|
-endif.
|
|
@ -539,7 +539,7 @@ manifest_printer(Manifest) ->
|
||||||
-ifdef(TEST).
|
-ifdef(TEST).
|
||||||
|
|
||||||
build_dummy_journal() ->
|
build_dummy_journal() ->
|
||||||
RootPath = "../test/inker",
|
RootPath = "../test/journal",
|
||||||
JournalFP = filepath(RootPath, journal_dir),
|
JournalFP = filepath(RootPath, journal_dir),
|
||||||
ManifestFP = filepath(RootPath, manifest_dir),
|
ManifestFP = filepath(RootPath, manifest_dir),
|
||||||
ok = filelib:ensure_dir(RootPath),
|
ok = filelib:ensure_dir(RootPath),
|
||||||
|
@ -577,7 +577,7 @@ clean_subdir(DirPath) ->
|
||||||
Files).
|
Files).
|
||||||
|
|
||||||
simple_buildmanifest_test() ->
|
simple_buildmanifest_test() ->
|
||||||
RootPath = "../test/inker",
|
RootPath = "../test/journal",
|
||||||
build_dummy_journal(),
|
build_dummy_journal(),
|
||||||
Res = build_manifest(["1.man"],
|
Res = build_manifest(["1.man"],
|
||||||
["nursery_1.cdb", "nursery_3.pnd"],
|
["nursery_1.cdb", "nursery_3.pnd"],
|
||||||
|
@ -596,7 +596,7 @@ simple_buildmanifest_test() ->
|
||||||
|
|
||||||
another_buildmanifest_test() ->
|
another_buildmanifest_test() ->
|
||||||
%% There is a rolled jounral file which is not yet in the manifest
|
%% There is a rolled jounral file which is not yet in the manifest
|
||||||
RootPath = "../test/inker",
|
RootPath = "../test/journal",
|
||||||
build_dummy_journal(),
|
build_dummy_journal(),
|
||||||
FN = filepath(RootPath, 3, new_journal),
|
FN = filepath(RootPath, 3, new_journal),
|
||||||
{ok, FileToRoll} = leveled_cdb:cdb_open_writer(FN),
|
{ok, FileToRoll} = leveled_cdb:cdb_open_writer(FN),
|
||||||
|
@ -628,7 +628,7 @@ another_buildmanifest_test() ->
|
||||||
|
|
||||||
|
|
||||||
empty_buildmanifest_test() ->
|
empty_buildmanifest_test() ->
|
||||||
RootPath = "../test/inker/",
|
RootPath = "../test/journal",
|
||||||
Res = build_manifest([],
|
Res = build_manifest([],
|
||||||
[],
|
[],
|
||||||
fun simple_manifest_reader/2,
|
fun simple_manifest_reader/2,
|
||||||
|
@ -649,7 +649,7 @@ empty_buildmanifest_test() ->
|
||||||
simplejournal_test() ->
|
simplejournal_test() ->
|
||||||
%% build up a database, and then open it through the gen_server wrap
|
%% build up a database, and then open it through the gen_server wrap
|
||||||
%% Get and Put some keys
|
%% Get and Put some keys
|
||||||
RootPath = "../test/inker",
|
RootPath = "../test/journal",
|
||||||
build_dummy_journal(),
|
build_dummy_journal(),
|
||||||
{ok, Ink1} = ink_start(#inker_options{root_path=RootPath,
|
{ok, Ink1} = ink_start(#inker_options{root_path=RootPath,
|
||||||
cdb_options=#cdb_options{}}),
|
cdb_options=#cdb_options{}}),
|
||||||
|
@ -666,7 +666,7 @@ simplejournal_test() ->
|
||||||
clean_testdir(RootPath).
|
clean_testdir(RootPath).
|
||||||
|
|
||||||
rollafile_simplejournal_test() ->
|
rollafile_simplejournal_test() ->
|
||||||
RootPath = "../test/inker",
|
RootPath = "../test/journal",
|
||||||
build_dummy_journal(),
|
build_dummy_journal(),
|
||||||
CDBopts = #cdb_options{max_size=300000},
|
CDBopts = #cdb_options{max_size=300000},
|
||||||
{ok, Ink1} = ink_start(#inker_options{root_path=RootPath,
|
{ok, Ink1} = ink_start(#inker_options{root_path=RootPath,
|
||||||
|
|
|
@ -197,15 +197,16 @@
|
||||||
levelzero_pending = ?L0PEND_RESET :: tuple(),
|
levelzero_pending = ?L0PEND_RESET :: tuple(),
|
||||||
levelzero_snapshot = [] :: list(),
|
levelzero_snapshot = [] :: list(),
|
||||||
memtable,
|
memtable,
|
||||||
backlog = false :: boolean()}).
|
backlog = false :: boolean(),
|
||||||
|
memtable_maxsize :: integer}).
|
||||||
|
|
||||||
|
|
||||||
%%%============================================================================
|
%%%============================================================================
|
||||||
%%% API
|
%%% API
|
||||||
%%%============================================================================
|
%%%============================================================================
|
||||||
|
|
||||||
pcl_start(RootDir) ->
|
pcl_start(PCLopts) ->
|
||||||
gen_server:start(?MODULE, [RootDir], []).
|
gen_server:start(?MODULE, [PCLopts], []).
|
||||||
|
|
||||||
pcl_pushmem(Pid, DumpList) ->
|
pcl_pushmem(Pid, DumpList) ->
|
||||||
%% Bookie to dump memory onto penciller
|
%% Bookie to dump memory onto penciller
|
||||||
|
@ -236,10 +237,20 @@ pcl_close(Pid) ->
|
||||||
%%% gen_server callbacks
|
%%% gen_server callbacks
|
||||||
%%%============================================================================
|
%%%============================================================================
|
||||||
|
|
||||||
init([RootPath]) ->
|
init([PCLopts]) ->
|
||||||
|
RootPath = PCLopts#penciller_options.root_path,
|
||||||
|
MaxTableSize = case PCLopts#penciller_options.max_inmemory_tablesize of
|
||||||
|
undefined ->
|
||||||
|
?MAX_TABLESIZE;
|
||||||
|
M ->
|
||||||
|
M
|
||||||
|
end,
|
||||||
TID = ets:new(?MEMTABLE, [ordered_set]),
|
TID = ets:new(?MEMTABLE, [ordered_set]),
|
||||||
{ok, Clerk} = leveled_clerk:clerk_new(self()),
|
{ok, Clerk} = leveled_clerk:clerk_new(self()),
|
||||||
InitState = #state{memtable=TID, clerk=Clerk, root_path=RootPath},
|
InitState = #state{memtable=TID,
|
||||||
|
clerk=Clerk,
|
||||||
|
root_path=RootPath,
|
||||||
|
memtable_maxsize=MaxTableSize},
|
||||||
|
|
||||||
%% Open manifest
|
%% Open manifest
|
||||||
ManifestPath = InitState#state.root_path ++ "/" ++ ?MANIFEST_FP ++ "/",
|
ManifestPath = InitState#state.root_path ++ "/" ++ ?MANIFEST_FP ++ "/",
|
||||||
|
@ -320,7 +331,7 @@ init([RootPath]) ->
|
||||||
handle_call({push_mem, DumpList}, _From, State) ->
|
handle_call({push_mem, DumpList}, _From, State) ->
|
||||||
StartWatch = os:timestamp(),
|
StartWatch = os:timestamp(),
|
||||||
Response = case assess_sqn(DumpList) of
|
Response = case assess_sqn(DumpList) of
|
||||||
{MinSQN, MaxSQN} when MaxSQN > MinSQN,
|
{MinSQN, MaxSQN} when MaxSQN >= MinSQN,
|
||||||
MinSQN >= State#state.ledger_sqn ->
|
MinSQN >= State#state.ledger_sqn ->
|
||||||
io:format("SQN check completed in ~w microseconds~n",
|
io:format("SQN check completed in ~w microseconds~n",
|
||||||
[timer:now_diff(os:timestamp(),StartWatch)]),
|
[timer:now_diff(os:timestamp(),StartWatch)]),
|
||||||
|
@ -436,6 +447,10 @@ terminate(_Reason, State) ->
|
||||||
file:rename(FileName ++ ".pnd", FileName ++ ".sft");
|
file:rename(FileName ++ ".pnd", FileName ++ ".sft");
|
||||||
{?L0PEND_RESET, [], L} when L == 0 ->
|
{?L0PEND_RESET, [], L} when L == 0 ->
|
||||||
io:format("No keys to dump from memory when closing~n");
|
io:format("No keys to dump from memory when closing~n");
|
||||||
|
{{true, L0Pid, _TS}, _, _} ->
|
||||||
|
leveled_sft:sft_close(L0Pid),
|
||||||
|
io:format("No opportunity to persist memory before closing "
|
||||||
|
++ "with ~w keys discarded~n", [length(Dump)]);
|
||||||
_ ->
|
_ ->
|
||||||
io:format("No opportunity to persist memory before closing "
|
io:format("No opportunity to persist memory before closing "
|
||||||
++ "with ~w keys discarded~n", [length(Dump)])
|
++ "with ~w keys discarded~n", [length(Dump)])
|
||||||
|
@ -481,7 +496,8 @@ push_to_memory(DumpList, State) ->
|
||||||
MemoryInsertion = do_push_to_mem(DumpList,
|
MemoryInsertion = do_push_to_mem(DumpList,
|
||||||
TableSize,
|
TableSize,
|
||||||
UpdState#state.memtable,
|
UpdState#state.memtable,
|
||||||
UpdState#state.levelzero_snapshot),
|
UpdState#state.levelzero_snapshot,
|
||||||
|
UpdState#state.memtable_maxsize),
|
||||||
|
|
||||||
case MemoryInsertion of
|
case MemoryInsertion of
|
||||||
{twist, ApproxTableSize, UpdSnapshot} ->
|
{twist, ApproxTableSize, UpdSnapshot} ->
|
||||||
|
@ -557,16 +573,16 @@ fetch(Key, Manifest, Level, FetchFun) ->
|
||||||
end
|
end
|
||||||
end.
|
end.
|
||||||
|
|
||||||
do_push_to_mem(DumpList, TableSize, MemTable, Snapshot) ->
|
do_push_to_mem(DumpList, TableSize, MemTable, Snapshot, MaxSize) ->
|
||||||
SW = os:timestamp(),
|
SW = os:timestamp(),
|
||||||
UpdSnapshot = lists:append(Snapshot, DumpList),
|
UpdSnapshot = lists:append(Snapshot, DumpList),
|
||||||
ets:insert(MemTable, DumpList),
|
ets:insert(MemTable, DumpList),
|
||||||
io:format("Push into memory timed at ~w microseconds~n",
|
io:format("Push into memory timed at ~w microseconds~n",
|
||||||
[timer:now_diff(os:timestamp(), SW)]),
|
[timer:now_diff(os:timestamp(), SW)]),
|
||||||
case TableSize + length(DumpList) of
|
case TableSize + length(DumpList) of
|
||||||
ApproxTableSize when ApproxTableSize > ?MAX_TABLESIZE ->
|
ApproxTableSize when ApproxTableSize > MaxSize ->
|
||||||
case ets:info(MemTable, size) of
|
case ets:info(MemTable, size) of
|
||||||
ActTableSize when ActTableSize > ?MAX_TABLESIZE ->
|
ActTableSize when ActTableSize > MaxSize ->
|
||||||
{roll, ActTableSize, UpdSnapshot};
|
{roll, ActTableSize, UpdSnapshot};
|
||||||
ActTableSize ->
|
ActTableSize ->
|
||||||
io:format("Table size is actually ~w~n", [ActTableSize]),
|
io:format("Table size is actually ~w~n", [ActTableSize]),
|
||||||
|
@ -769,14 +785,19 @@ rename_manifest_files(RootPath, NewMSN) ->
|
||||||
file:rename(filepath(RootPath, NewMSN, pending_manifest),
|
file:rename(filepath(RootPath, NewMSN, pending_manifest),
|
||||||
filepath(RootPath, NewMSN, current_manifest)).
|
filepath(RootPath, NewMSN, current_manifest)).
|
||||||
|
|
||||||
|
filepath(RootPath, manifest) ->
|
||||||
|
RootPath ++ "/" ++ ?MANIFEST_FP;
|
||||||
|
filepath(RootPath, files) ->
|
||||||
|
RootPath ++ "/" ++ ?FILES_FP.
|
||||||
|
|
||||||
filepath(RootPath, NewMSN, pending_manifest) ->
|
filepath(RootPath, NewMSN, pending_manifest) ->
|
||||||
RootPath ++ "/" ++ ?MANIFEST_FP ++ "/" ++ "nonzero_"
|
filepath(RootPath, manifest) ++ "/" ++ "nonzero_"
|
||||||
++ integer_to_list(NewMSN) ++ "." ++ ?PENDING_FILEX;
|
++ integer_to_list(NewMSN) ++ "." ++ ?PENDING_FILEX;
|
||||||
filepath(RootPath, NewMSN, current_manifest) ->
|
filepath(RootPath, NewMSN, current_manifest) ->
|
||||||
RootPath ++ "/" ++ ?MANIFEST_FP ++ "/" ++ "nonzero_"
|
filepath(RootPath, manifest) ++ "/" ++ "nonzero_"
|
||||||
++ integer_to_list(NewMSN) ++ "." ++ ?CURRENT_FILEX;
|
++ integer_to_list(NewMSN) ++ "." ++ ?CURRENT_FILEX;
|
||||||
filepath(RootPath, NewMSN, new_merge_files) ->
|
filepath(RootPath, NewMSN, new_merge_files) ->
|
||||||
RootPath ++ "/" ++ ?FILES_FP ++ "/" ++ integer_to_list(NewMSN).
|
filepath(RootPath, files) ++ "/" ++ integer_to_list(NewMSN).
|
||||||
|
|
||||||
update_deletions([], _NewMSN, UnreferencedFiles) ->
|
update_deletions([], _NewMSN, UnreferencedFiles) ->
|
||||||
UnreferencedFiles;
|
UnreferencedFiles;
|
||||||
|
@ -822,6 +843,24 @@ assess_sqn([HeadKey|Tail], MinSQN, MaxSQN) ->
|
||||||
%%% Test
|
%%% Test
|
||||||
%%%============================================================================
|
%%%============================================================================
|
||||||
|
|
||||||
|
-ifdef(TEST).
|
||||||
|
|
||||||
|
clean_testdir(RootPath) ->
|
||||||
|
clean_subdir(filepath(RootPath, manifest)),
|
||||||
|
clean_subdir(filepath(RootPath, files)).
|
||||||
|
|
||||||
|
clean_subdir(DirPath) ->
|
||||||
|
case filelib:is_dir(DirPath) of
|
||||||
|
true ->
|
||||||
|
{ok, Files} = file:list_dir(DirPath),
|
||||||
|
lists:foreach(fun(FN) -> file:delete(filename:join(DirPath, FN)),
|
||||||
|
io:format("Delete file ~s/~s~n",
|
||||||
|
[DirPath, FN])
|
||||||
|
end,
|
||||||
|
Files);
|
||||||
|
false ->
|
||||||
|
ok
|
||||||
|
end.
|
||||||
|
|
||||||
compaction_work_assessment_test() ->
|
compaction_work_assessment_test() ->
|
||||||
L0 = [{{o, "B1", "K1"}, {o, "B3", "K3"}, dummy_pid}],
|
L0 = [{{o, "B1", "K1"}, {o, "B3", "K3"}, dummy_pid}],
|
||||||
|
@ -854,4 +893,51 @@ confirm_delete_test() ->
|
||||||
?assertMatch(R2, false),
|
?assertMatch(R2, false),
|
||||||
RegisteredIterators3 = [{dummy_pid, 9}, {dummy_pid, 12}],
|
RegisteredIterators3 = [{dummy_pid, 9}, {dummy_pid, 12}],
|
||||||
R3 = confirm_delete(Filename, UnreferencedFiles, RegisteredIterators3),
|
R3 = confirm_delete(Filename, UnreferencedFiles, RegisteredIterators3),
|
||||||
?assertMatch(R3, false).
|
?assertMatch(R3, false).
|
||||||
|
|
||||||
|
|
||||||
|
simple_server_test() ->
|
||||||
|
RootPath = "../test/ledger",
|
||||||
|
clean_testdir(RootPath),
|
||||||
|
{ok, PCL} = pcl_start(#penciller_options{root_path=RootPath,
|
||||||
|
max_inmemory_tablesize=1000}),
|
||||||
|
Key1 = {{o,"Bucket0001", "Key0001"},1, {active, infinity}, null},
|
||||||
|
KL1 = lists:sort(leveled_sft:generate_randomkeys({1000, 2})),
|
||||||
|
Key2 = {{o,"Bucket0002", "Key0002"},1002, {active, infinity}, null},
|
||||||
|
KL2 = lists:sort(leveled_sft:generate_randomkeys({1000, 1002})),
|
||||||
|
Key3 = {{o,"Bucket0003", "Key0003"},2002, {active, infinity}, null},
|
||||||
|
ok = pcl_pushmem(PCL, [Key1]),
|
||||||
|
R1 = pcl_fetch(PCL, {o,"Bucket0001", "Key0001"}),
|
||||||
|
?assertMatch(R1, Key1),
|
||||||
|
ok = pcl_pushmem(PCL, KL1),
|
||||||
|
R2 = pcl_fetch(PCL, {o,"Bucket0001", "Key0001"}),
|
||||||
|
?assertMatch(R2, Key1),
|
||||||
|
S1 = pcl_pushmem(PCL, [Key2]),
|
||||||
|
if S1 == pause -> timer:sleep(2); true -> ok end,
|
||||||
|
R3 = pcl_fetch(PCL, {o,"Bucket0001", "Key0001"}),
|
||||||
|
R4 = pcl_fetch(PCL, {o,"Bucket0002", "Key0002"}),
|
||||||
|
?assertMatch(R3, Key1),
|
||||||
|
?assertMatch(R4, Key2),
|
||||||
|
S2 = pcl_pushmem(PCL, KL2),
|
||||||
|
if S2 == pause -> timer:sleep(2000); true -> ok end,
|
||||||
|
S3 = pcl_pushmem(PCL, [Key3]),
|
||||||
|
if S3 == pause -> timer:sleep(2000); true -> ok end,
|
||||||
|
R5 = pcl_fetch(PCL, {o,"Bucket0001", "Key0001"}),
|
||||||
|
R6 = pcl_fetch(PCL, {o,"Bucket0002", "Key0002"}),
|
||||||
|
R7 = pcl_fetch(PCL, {o,"Bucket0003", "Key0003"}),
|
||||||
|
?assertMatch(R5, Key1),
|
||||||
|
?assertMatch(R6, Key2),
|
||||||
|
?assertMatch(R7, Key3),
|
||||||
|
ok = pcl_close(PCL),
|
||||||
|
{ok, PCLr} = pcl_start(#penciller_options{root_path=RootPath,
|
||||||
|
max_inmemory_tablesize=1000}),
|
||||||
|
R8 = pcl_fetch(PCLr, {o,"Bucket0001", "Key0001"}),
|
||||||
|
R9 = pcl_fetch(PCLr, {o,"Bucket0002", "Key0002"}),
|
||||||
|
R10 = pcl_fetch(PCLr, {o,"Bucket0003", "Key0003"}),
|
||||||
|
?assertMatch(R8, Key1),
|
||||||
|
?assertMatch(R9, Key2),
|
||||||
|
?assertMatch(R10, Key3),
|
||||||
|
ok = pcl_close(PCLr),
|
||||||
|
clean_testdir(RootPath).
|
||||||
|
|
||||||
|
-endif.
|
|
@ -200,7 +200,7 @@
|
||||||
filter_pointer :: integer(),
|
filter_pointer :: integer(),
|
||||||
summ_pointer :: integer(),
|
summ_pointer :: integer(),
|
||||||
summ_length :: integer(),
|
summ_length :: integer(),
|
||||||
filename :: string(),
|
filename = "not set" :: string(),
|
||||||
handle :: file:fd(),
|
handle :: file:fd(),
|
||||||
background_complete = false :: boolean(),
|
background_complete = false :: boolean(),
|
||||||
background_failure = "Unknown" :: string(),
|
background_failure = "Unknown" :: string(),
|
||||||
|
@ -387,7 +387,12 @@ terminate(Reason, State) ->
|
||||||
ok = file:close(State#state.handle),
|
ok = file:close(State#state.handle),
|
||||||
ok = file:delete(State#state.filename);
|
ok = file:delete(State#state.filename);
|
||||||
_ ->
|
_ ->
|
||||||
ok = file:close(State#state.handle)
|
case State#state.handle of
|
||||||
|
undefined ->
|
||||||
|
ok;
|
||||||
|
Handle ->
|
||||||
|
file:close(Handle)
|
||||||
|
end
|
||||||
end.
|
end.
|
||||||
|
|
||||||
code_change(_OldVsn, State, _Extra) ->
|
code_change(_OldVsn, State, _Extra) ->
|
||||||
|
@ -520,6 +525,7 @@ complete_file(Handle, FileMD, KL1, KL2, Level, Rename) ->
|
||||||
false ->
|
false ->
|
||||||
open_file(FileMD);
|
open_file(FileMD);
|
||||||
{true, OldName, NewName} ->
|
{true, OldName, NewName} ->
|
||||||
|
io:format("Renaming file from ~s to ~s~n", [OldName, NewName]),
|
||||||
ok = file:rename(OldName, NewName),
|
ok = file:rename(OldName, NewName),
|
||||||
open_file(FileMD#state{filename=NewName})
|
open_file(FileMD#state{filename=NewName})
|
||||||
end,
|
end,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue