diff options
Diffstat (limited to 'lib/kernel')
-rw-r--r-- | lib/kernel/doc/src/error_logger.xml | 2 | ||||
-rw-r--r-- | lib/kernel/doc/src/kernel_app.xml | 2 | ||||
-rw-r--r-- | lib/kernel/src/auth.erl | 12 | ||||
-rw-r--r-- | lib/kernel/src/code_server.erl | 10 | ||||
-rw-r--r-- | lib/kernel/src/gen_sctp.erl | 6 | ||||
-rw-r--r-- | lib/kernel/src/global.erl | 10 | ||||
-rw-r--r-- | lib/kernel/test/code_SUITE.erl | 49 | ||||
-rw-r--r-- | lib/kernel/test/erl_prim_loader_SUITE.erl | 8 | ||||
-rw-r--r-- | lib/kernel/test/file_SUITE.erl | 167 | ||||
-rwxr-xr-x | lib/kernel/test/inet_res_SUITE_data/run-named | 10 | ||||
-rw-r--r-- | lib/kernel/test/prim_file_SUITE.erl | 109 |
11 files changed, 303 insertions, 82 deletions
diff --git a/lib/kernel/doc/src/error_logger.xml b/lib/kernel/doc/src/error_logger.xml index 2d95f96ac7..95b23e4aef 100644 --- a/lib/kernel/doc/src/error_logger.xml +++ b/lib/kernel/doc/src/error_logger.xml @@ -49,7 +49,7 @@ that events are logged to file instead, or not logged at all, see <seealso marker="kernel_app">kernel(6)</seealso>.</p> <p>Also the SASL application, if started, adds its own event - handler, which by default writes supervisor-, crash- and progress + handler, which by default writes supervisor, crash and progress reports to tty. See <seealso marker="sasl:sasl_app">sasl(6)</seealso>.</p> <p>It is recommended that user defined applications should report diff --git a/lib/kernel/doc/src/kernel_app.xml b/lib/kernel/doc/src/kernel_app.xml index 0f71a4f0f2..63fdc223f4 100644 --- a/lib/kernel/doc/src/kernel_app.xml +++ b/lib/kernel/doc/src/kernel_app.xml @@ -104,7 +104,7 @@ that node. <c>Value</c> is one of:</p> <taglist> <tag><c>never</c></tag> - <item>Connections are never automatically connected, they + <item>Connections are never automatically established, they must be explicitly connected. See <c>net_kernel(3)</c>.</item> <tag><c>once</c></tag> <item>Connections will be established automatically, but only diff --git a/lib/kernel/src/auth.erl b/lib/kernel/src/auth.erl index c329a5652a..252c20ac4e 100644 --- a/lib/kernel/src/auth.erl +++ b/lib/kernel/src/auth.erl @@ -381,13 +381,17 @@ create_cookie(Name) -> case {R1, R2} of {ok, ok} -> ok; - {{error,_Reason}, _} -> - {error, "Failed to create cookie file"}; + {{error,Reason}, _} -> + {error, + lists:flatten( + io_lib:format("Failed to write to cookie file '~s': ~p", [Name, Reason]))}; {ok, {error, Reason}} -> {error, "Failed to change mode: " ++ atom_to_list(Reason)} end; - {error,_Reason} -> - {error, "Failed to create cookie file"} + {error,Reason} -> + {error, + lists:flatten( + io_lib:format("Failed to create cookie file '~s': ~p", [Name, Reason]))} end. random_cookie(0, _, Result) -> diff --git a/lib/kernel/src/code_server.erl b/lib/kernel/src/code_server.erl index 32a12e2b52..5d4f2eb70c 100644 --- a/lib/kernel/src/code_server.erl +++ b/lib/kernel/src/code_server.erl @@ -1317,15 +1317,21 @@ int_list([H|T]) when is_integer(H) -> int_list(T); int_list([_|_]) -> false; int_list([]) -> true. +load_file(Mod0, {From,_}=Caller, St0) -> + Mod = to_atom(Mod0), + case pending_on_load(Mod, From, St0) of + no -> load_file_1(Mod, Caller, St0); + {yes,St} -> {noreply,St} + end. -load_file(Mod, Caller, #state{path=Path,cache=no_cache}=St) -> +load_file_1(Mod, Caller, #state{path=Path,cache=no_cache}=St) -> case mod_to_bin(Path, Mod) of error -> {reply,{error,nofile},St}; {Mod,Binary,File} -> try_load_module(File, Mod, Binary, Caller, St) end; -load_file(Mod, Caller, #state{cache=Cache}=St0) -> +load_file_1(Mod, Caller, #state{cache=Cache}=St0) -> Key = {obj,Mod}, case ets:lookup(Cache, Key) of [] -> diff --git a/lib/kernel/src/gen_sctp.erl b/lib/kernel/src/gen_sctp.erl index 77ca26b845..d8954f0cf7 100644 --- a/lib/kernel/src/gen_sctp.erl +++ b/lib/kernel/src/gen_sctp.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2007-2011. All Rights Reserved. +%% Copyright Ericsson AB 2007-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -314,7 +314,7 @@ eof_or_abort(S, AssocId, Action) -> -spec send(Socket, SndRcvInfo, Data) -> ok | {error, Reason} when Socket :: sctp_socket(), SndRcvInfo :: #sctp_sndrcvinfo{}, - Data :: binary | iolist(), + Data :: binary() | iolist(), Reason :: term(). %% Full-featured send. Rarely needed. @@ -331,7 +331,7 @@ send(S, SRI, Data) -> Socket :: sctp_socket(), Assoc :: #sctp_assoc_change{} | assoc_id(), Stream :: integer(), - Data :: binary | iolist(), + Data :: binary() | iolist(), Reason :: term(). send(S, #sctp_assoc_change{assoc_id=AssocId}, Stream, Data) diff --git a/lib/kernel/src/global.erl b/lib/kernel/src/global.erl index fa97614eca..7da33859bf 100644 --- a/lib/kernel/src/global.erl +++ b/lib/kernel/src/global.erl @@ -280,13 +280,13 @@ unregister_name(Name) -> gen_server:call(global_name_server, {registrar, Fun}, infinity) end. --spec re_register_name(Name, Pid) -> _ when +-spec re_register_name(Name, Pid) -> 'yes' when Name :: term(), Pid :: pid(). re_register_name(Name, Pid) when is_pid(Pid) -> re_register_name(Name, Pid, fun random_exit_name/3). --spec re_register_name(Name, Pid, Resolve) -> _ when +-spec re_register_name(Name, Pid, Resolve) -> 'yes' when Name :: term(), Pid :: pid(), Resolve :: method(). @@ -1965,7 +1965,7 @@ resolve_it(Method, Name, Pid1, Pid2) -> minmax(P1,P2) -> if node(P1) < node(P2) -> {P1, P2}; true -> {P2, P1} end. --spec random_exit_name(Name, Pid1, Pid2) -> 'none' when +-spec random_exit_name(Name, Pid1, Pid2) -> pid() when Name :: term(), Pid1 :: pid(), Pid2 :: pid(). @@ -1976,7 +1976,7 @@ random_exit_name(Name, Pid, Pid2) -> exit(Max, kill), Min. --spec random_notify_name(Name, Pid1, Pid2) -> 'none' when +-spec random_notify_name(Name, Pid1, Pid2) -> pid() when Name :: term(), Pid1 :: pid(), Pid2 :: pid(). @@ -2175,7 +2175,7 @@ get_own_nodes() -> start_the_registrar() -> spawn_link(fun() -> loop_the_registrar() end). - + loop_the_registrar() -> receive {trans_all_known, Fun, From} -> diff --git a/lib/kernel/test/code_SUITE.erl b/lib/kernel/test/code_SUITE.erl index 10ab3e4370..99b0cd2ffb 100644 --- a/lib/kernel/test/code_SUITE.erl +++ b/lib/kernel/test/code_SUITE.erl @@ -30,9 +30,9 @@ load_cached/1, start_node_with_cache/1, add_and_rehash/1, where_is_file_cached/1, where_is_file_no_cache/1, purge_stacktrace/1, mult_lib_roots/1, bad_erl_libs/1, - code_archive/1, code_archive2/1, on_load/1, - big_boot_embedded/1, - on_load_embedded/1, on_load_errors/1, native_early_modules/1]). + code_archive/1, code_archive2/1, on_load/1, on_load_binary/1, + on_load_embedded/1, on_load_errors/1, big_boot_embedded/1, + native_early_modules/1]). -export([init_per_testcase/2, end_per_testcase/2, init_per_suite/1, end_per_suite/1, @@ -55,8 +55,8 @@ all() -> add_and_rehash, where_is_file_no_cache, where_is_file_cached, purge_stacktrace, mult_lib_roots, bad_erl_libs, code_archive, code_archive2, on_load, - on_load_embedded, big_boot_embedded, on_load_errors, - native_early_modules]. + on_load_binary, on_load_embedded, on_load_errors, + big_boot_embedded, native_early_modules]. groups() -> []. @@ -1286,6 +1286,45 @@ on_load_wait_for_all([Ref|T]) -> end; on_load_wait_for_all([]) -> ok. +on_load_binary(_) -> + Master = on_load_binary_test_case_process, + register(Master, self()), + + %% Construct, compile and pretty-print. + Mod = on_load_binary, + File = atom_to_list(Mod) ++ ".erl", + Forms = [{attribute,1,file,{File,1}}, + {attribute,1,module,Mod}, + {attribute,2,export,[{ok,0}]}, + {attribute,3,on_load,{init,0}}, + {function,5,init,0, + [{clause,5,[],[], + [{op,6,'!', + {atom,6,Master}, + {tuple,6,[{atom,6,Mod},{call,6,{atom,6,self},[]}]}}, + {'receive',7,[{clause,8,[{atom,8,go}],[],[{atom,8,ok}]}]}]}]}, + {function,11,ok,0,[{clause,11,[],[],[{atom,11,true}]}]}], + {ok,Mod,Bin} = compile:forms(Forms, [report]), + [io:put_chars(erl_pp:form(F)) || F <- Forms], + + {Pid1,Ref1} = spawn_monitor(fun() -> + code:load_binary(Mod, File, Bin), + true = on_load_binary:ok() + end), + receive {Mod,OnLoadPid} -> ok end, + {Pid2,Ref2} = spawn_monitor(fun() -> + true = on_load_binary:ok() + end), + erlang:yield(), + OnLoadPid ! go, + receive {'DOWN',Ref1,process,Pid1,Exit1} -> ok end, + receive {'DOWN',Ref2,process,Pid2,Exit2} -> ok end, + normal = Exit1, + normal = Exit2, + true = code:delete(on_load_binary), + false = code:purge(on_load_binary), + ok. + on_load_embedded(Config) when is_list(Config) -> try on_load_embedded_1(Config) diff --git a/lib/kernel/test/erl_prim_loader_SUITE.erl b/lib/kernel/test/erl_prim_loader_SUITE.erl index 7599a89779..d0d52c5ea7 100644 --- a/lib/kernel/test/erl_prim_loader_SUITE.erl +++ b/lib/kernel/test/erl_prim_loader_SUITE.erl @@ -175,10 +175,10 @@ wait_really_started(Node, N) -> inet_disconnects(doc) -> ["Start a node using the 'inet' loading method, ", "then lose the connection."]; inet_disconnects(Config) when is_list(Config) -> - case os:type() of - vxworks -> - {comment, "VxWorks: tested separately"}; - _ -> + case test_server:is_native(erl_boot_server) of + true -> + {skip,"erl_boot_server is native"}; + false -> ?line Name = erl_prim_test_inet_disconnects, ?line Host = host(), ?line Cookie = atom_to_list(erlang:get_cookie()), diff --git a/lib/kernel/test/file_SUITE.erl b/lib/kernel/test/file_SUITE.erl index 85346762ac..2b6af7e1fb 100644 --- a/lib/kernel/test/file_SUITE.erl +++ b/lib/kernel/test/file_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2011. All Rights Reserved. +%% Copyright Ericsson AB 1996-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -78,7 +78,7 @@ -export([altname/1]). --export([large_file/1]). +-export([large_file/1, large_write/1]). -export([read_line_1/1, read_line_2/1, read_line_3/1,read_line_4/1]). @@ -92,6 +92,8 @@ -export([bytes/2, iterate/3]). +%% System probe functions that might be handy to check from the shell +-export([disc_free/1, memsize/0]). -include_lib("test_server/include/test_server.hrl"). -include_lib("kernel/include/file.hrl"). @@ -106,7 +108,7 @@ all() -> {group, compression}, {group, links}, copy, delayed_write, read_ahead, segment_read, segment_write, ipread, pid2name, interleaved_read_write, otp_5814, - large_file, read_line_1, read_line_2, read_line_3, + large_file, large_write, read_line_1, read_line_2, read_line_3, read_line_4, standard_io]. groups() -> @@ -143,6 +145,13 @@ end_per_group(_GroupName, Config) -> init_per_suite(Config) when is_list(Config) -> + SaslConfig = case application:start(sasl) of + {error, {already_started, sasl}} -> + []; + ok -> + [{sasl,started}] + end, + ok = application:start(os_mon), case os:type() of {win32, _} -> Priv = ?config(priv_dir, Config), @@ -154,9 +163,9 @@ init_per_suite(Config) when is_list(Config) -> {ok, _} -> [] end, - ?FILE_INIT(HasAccessTime++Config); + ?FILE_INIT(HasAccessTime++Config++SaslConfig); _ -> - ?FILE_INIT(Config) + ?FILE_INIT(Config++SaslConfig) end. end_per_suite(Config) when is_list(Config) -> @@ -166,6 +175,13 @@ end_per_suite(Config) when is_list(Config) -> _ -> ok end, + application:stop(os_mon), + case proplists:get_value(sasl, Config) of + started -> + application:stop(sasl); + _Else -> + ok + end, ?FILE_FINI(Config). init_per_testcase(_Func, Config) -> @@ -394,6 +410,7 @@ make_del_dir(Config) when is_list(Config) -> %% Don't worry ;-) the parent directory should never be empty, right? ?line case ?FILE_MODULE:del_dir('..') of {error, eexist} -> ok; + {error, eacces} -> ok; %OpenBSD {error, einval} -> ok %FreeBSD end, ?line {error, enoent} = ?FILE_MODULE:del_dir(""), @@ -3287,50 +3304,13 @@ large_file(suite) -> large_file(doc) -> ["Tests positioning in large files (> 4G)"]; large_file(Config) when is_list(Config) -> - case {os:type(),os:version()} of - {{win32,nt},_} -> - do_large_file(Config); - {{unix,sunos},{A,B,C}} - when A == 5, B == 5, C >= 1; A == 5, B >= 6; A >= 6 -> - do_large_file(Config); - {{unix,Unix},_} when Unix =/= sunos -> - N = unix_free(Config), - io:format("Free: ~w KByte~n", [N]), - if N < 5 * (1 bsl 20) -> - %% Less than 5 GByte free - {skipped,"Less than 5 GByte free"}; - true -> - do_large_file(Config) - end; - _ -> - {skipped,"Only supported on Win32, Unix or SunOS >= 5.5.1"} - end. + run_large_file_test(Config, + fun(Name) -> do_large_file(Name) end, + "_large_file"). -unix_free(Config) -> - Cmd = ["df -k '",?config(priv_dir, Config),"'"], - DF0 = os:cmd(Cmd), - io:format("$ ~s~n~s", [Cmd,DF0]), - [$\n|DF1] = lists:dropwhile(fun ($\n) -> false; (_) -> true end, DF0), - {ok,[N],_} = io_lib:fread(" ~*s ~d", DF1), - N. +do_large_file(Name) -> + ?line Watchdog = ?t:timetrap(?t:minutes(20)), -do_large_file(Config) -> - ?line Watchdog = ?t:timetrap(?t:minutes(5)), - %% - ?line Name = filename:join(?config(priv_dir, Config), - ?MODULE_STRING ++ "_large_file"), - ?line Tester = self(), - Deleter = - spawn( - fun() -> - Mref = erlang:monitor(process, Tester), - receive - {'DOWN',Mref,_,_,_} -> ok; - {Tester,done} -> ok - end, - ?FILE_MODULE:delete(Name) - end), - %% ?line S = "1234567890", L = length(S), R = lists:reverse(S), @@ -3366,15 +3346,36 @@ do_large_file(Config) -> ?line {ok,R} = ?FILE_MODULE:read(F1, L+1), ?line ok = ?FILE_MODULE:close(F1), %% - ?line Mref = erlang:monitor(process, Deleter), - ?line Deleter ! {Tester,done}, - ?line receive {'DOWN',Mref,_,_,_} -> ok end, - %% ?line ?t:timetrap_cancel(Watchdog), ok. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +large_write(Config) when is_list(Config) -> + run_large_file_test(Config, + fun(Name) -> do_large_write(Name) end, + "_large_write"). + +do_large_write(Name) -> + Memsize = memsize(), + io:format("Memsize = ~w Bytes~n", [Memsize]), + case {erlang:system_info(wordsize),Memsize} of + {4,_} -> + {skip,"Needs a 64-bit emulator"}; + {8,N} when N < 6 bsl 30 -> + {skip, + "This machine has < 6 GB memory: " + ++integer_to_list(N)}; + {8,_} -> + Size = 4*1024*1024*1024+1, + Bin = <<0:Size/unit:8>>, + ok = file:write_file(Name, Bin), + {ok,#file_info{size=Size}} = file:read_file_info(Name), + ok + end. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + response_analysis(Module, Function, Arguments) -> @@ -3950,3 +3951,67 @@ flush(Msgs) -> after 0 -> lists:reverse(Msgs) end. + +%%% +%%% Support for testing large files. +%%% + +run_large_file_test(Config, Run, Name) -> + case {os:type(),os:version()} of + {{win32,nt},_} -> + do_run_large_file_test(Config, Run, Name); + {{unix,sunos},OsVersion} when OsVersion < {5,5,1} -> + {skip,"Only supported on Win32, Unix or SunOS >= 5.5.1"}; + {{unix,_},_} -> + N = disc_free(?config(priv_dir, Config)), + io:format("Free disk: ~w KByte~n", [N]), + if N < 5 * (1 bsl 20) -> + %% Less than 5 GByte free + {skip,"Less than 5 GByte free"}; + true -> + do_run_large_file_test(Config, Run, Name) + end; + _ -> + {skip,"Only supported on Win32, Unix or SunOS >= 5.5.1"} + end. + + +do_run_large_file_test(Config, Run, Name0) -> + Name = filename:join(?config(priv_dir, Config), + ?MODULE_STRING ++ Name0), + + %% Set up a process that will delete this file. + Tester = self(), + Deleter = + spawn( + fun() -> + Mref = erlang:monitor(process, Tester), + receive + {'DOWN',Mref,_,_,_} -> ok; + {Tester,done} -> ok + end, + ?FILE_MODULE:delete(Name) + end), + + %% Run the test case. + Res = Run(Name), + + %% Delete file and finish deleter process. + Mref = erlang:monitor(process, Deleter), + Deleter ! {Tester,done}, + receive {'DOWN',Mref,_,_,_} -> ok end, + + Res. + +disc_free(Path) -> + Data = disksup:get_disk_data(), + {_,Tot,Perc} = hd(lists:filter( + fun({P,_Size,_Full}) -> + lists:prefix(filename:nativename(P), + filename:nativename(Path)) + end, lists:reverse(lists:sort(Data)))), + round(Tot * (1-(Perc/100))). + +memsize() -> + {Tot,_Used,_} = memsup:get_memory_data(), + Tot. diff --git a/lib/kernel/test/inet_res_SUITE_data/run-named b/lib/kernel/test/inet_res_SUITE_data/run-named index 619e456b3f..211d2c7af7 100755 --- a/lib/kernel/test/inet_res_SUITE_data/run-named +++ b/lib/kernel/test/inet_res_SUITE_data/run-named @@ -2,7 +2,7 @@ ## ## %CopyrightBegin% ## -## Copyright Ericsson AB 2009-2011. All Rights Reserved. +## Copyright Ericsson AB 2009-2012. All Rights Reserved. ## ## The contents of this file are subject to the Erlang Public License, ## Version 1.1, (the "License"); you may not use this file except in @@ -159,17 +159,17 @@ echo "Command: $NAMED $NAMED_FG -c $CONF_FILE" $NAMED $NAMED_FG -c "$CONF_FILE" >"$LOG_FILE" 2>&1 </dev/null & NAMED_PID=$! echo "Pid: $NAMED_PID" -trap "kill -TERM $NAMED_PID >/dev/null 2>&1; wait $NAMED_PID >/dev/null 2>&1" \ +trap "kill $NAMED_PID >/dev/null 2>&1; wait $NAMED_PID >/dev/null 2>&1" \ 0 1 2 3 15 sleep 5 # Give name server time to load its zone files -if ps p $NAMED_PID; then +if ps -p $NAMED_PID >/dev/null 2>&1 || ps p $NAMED_PID >/dev/null 2>&1; then echo "Running: Enter \`\`quit'' to terminate nameserver[$NAMED_PID]..." while read LINE; do test :"$LINE" = :'quit' && break done + echo "Closing: Terminating nameserver..." else - wait $NAMED_PID; error "$NAMED failed to start" + error "$NAMED failed to start" fi -echo "Closing: Terminating nameserver..." diff --git a/lib/kernel/test/prim_file_SUITE.erl b/lib/kernel/test/prim_file_SUITE.erl index ccf26ee034..3e2202922c 100644 --- a/lib/kernel/test/prim_file_SUITE.erl +++ b/lib/kernel/test/prim_file_SUITE.erl @@ -52,6 +52,10 @@ list_dir_limit/1]). -export([advise/1]). +-export([large_write/1]). + +%% System probe functions that might be handy to check from the shell +-export([unix_free/1]). -include_lib("test_server/include/test_server.hrl"). -include_lib("kernel/include/file.hrl"). @@ -83,7 +87,7 @@ groups() -> cur_dir_1a, cur_dir_1b]}, {files, [], [{group, open}, {group, pos}, {group, file_info}, - truncate, sync, datasync, advise]}, + truncate, sync, datasync, advise, large_write]}, {open, [], [open1, modes, close, access, read_write, pread_write, append, exclusive]}, @@ -290,6 +294,7 @@ make_del_dir(Config, Handle, Suffix) -> %% Don't worry ;-) the parent directory should never be empty, right? ?line case ?PRIM_FILE_call(del_dir, Handle, [".."]) of {error, eexist} -> ok; + {error, eacces} -> ok; %OpenBSD {error, einval} -> ok %FreeBSD end, ?line {error, enoent} = ?PRIM_FILE_call(del_dir, Handle, [""]), @@ -1322,6 +1327,41 @@ advise(Config) when is_list(Config) -> ?line test_server:timetrap_cancel(Dog), ok. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +large_write(Config) when is_list(Config) -> + run_large_file_test(Config, + fun(Name) -> do_large_write(Name) end, + "_large_write"). + +do_large_write(Name) -> + Dog = test_server:timetrap(test_server:minutes(60)), + ChunkSize = (256 bsl 20) + 1, % 256 M + 1 + Chunks = 16, % times 16 -> 4 G + 16 + Base = 100, + Interleave = lists:seq(Base+1, Base+Chunks), + Chunk = <<0:ChunkSize/unit:8>>, + Data = zip_data(lists:duplicate(Chunks, Chunk), Interleave), + Size = Chunks * ChunkSize + Chunks, % 4 G + 32 + Wordsize = erlang:system_info(wordsize), + case prim_file:write_file(Name, Data) of + ok when Wordsize =:= 8 -> + {ok,#file_info{size=Size}} = file:read_file_info(Name), + {ok,Fd} = prim_file:open(Name, [read]), + check_large_write(Dog, Fd, ChunkSize, 0, Interleave); + {error,einval} when Wordsize =:= 4 -> + ok + end. + +check_large_write(Dog, Fd, ChunkSize, Pos, [X|Interleave]) -> + Pos1 = Pos + ChunkSize, + {ok,Pos1} = prim_file:position(Fd, {cur,ChunkSize}), + {ok,[X]} = prim_file:read(Fd, 1), + check_large_write(Dog, Fd, ChunkSize, Pos1+1, Interleave); +check_large_write(Dog, Fd, _, _, []) -> + eof = prim_file:read(Fd, 1), + test_server:timetrap_cancel(Dog), + ok. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -2044,3 +2084,70 @@ list_dir_limit_cleanup(Dir, Handle, N, Cnt) -> ?PRIM_FILE:delete(Handle, filename:join(Dir, Name)), list_dir_limit_cleanup(Dir, Handle, N, Cnt+1). +%%% +%%% Support for testing large files. +%%% + +run_large_file_test(Config, Run, Name) -> + case {os:type(),os:version()} of + {{win32,nt},_} -> + do_run_large_file_test(Config, Run, Name); + {{unix,sunos},OsVersion} when OsVersion < {5,5,1} -> + {skip,"Only supported on Win32, Unix or SunOS >= 5.5.1"}; + {{unix,_},_} -> + N = unix_free(?config(priv_dir, Config)), + io:format("Free disk: ~w KByte~n", [N]), + if N < 5 bsl 20 -> + %% Less than 5 GByte free + {skip,"Less than 5 GByte free disk"}; + true -> + do_run_large_file_test(Config, Run, Name) + end; + _ -> + {skip,"Only supported on Win32, Unix or SunOS >= 5.5.1"} + end. + + +do_run_large_file_test(Config, Run, Name0) -> + Name = filename:join(?config(priv_dir, Config), + ?MODULE_STRING ++ Name0), + + %% Set up a process that will delete this file. + Tester = self(), + Deleter = + spawn( + fun() -> + Mref = erlang:monitor(process, Tester), + receive + {'DOWN',Mref,_,_,_} -> ok; + {Tester,done} -> ok + end, + prim_file:delete(Name) + end), + + %% Run the test case. + Res = Run(Name), + + %% Delete file and finish deleter process. + Mref = erlang:monitor(process, Deleter), + Deleter ! {Tester,done}, + receive {'DOWN',Mref,_,_,_} -> ok end, + + Res. + +unix_free(Path) -> + Cmd = ["df -k '",Path,"'"], + DF0 = os:cmd(Cmd), + io:format("$ ~s~n~s", [Cmd,DF0]), + Lines = re:split(DF0, "\n", [trim,{return,list}]), + Last = lists:last(Lines), + RE = "^[^\\s]*\\s+\\d+\\s+\\d+\\s+(\\d+)", + {match,[Avail]} = re:run(Last, RE, [{capture,all_but_first,list}]), + list_to_integer(Avail). + +zip_data([A|As], [B|Bs]) -> + [[A,B]|zip_data(As, Bs)]; +zip_data([], Bs) -> + Bs; +zip_data(As, []) -> + As. |