%%% Copyright (c) 2014, NORDUnet A/S. %%% See LICENSE for licensing information. -module(util). -export([tempfilename/1, fsync/1, exit_with_error/3, check_error/3, write_tempfile_and_rename/3, spawn_and_wait/1]). -spec tempfilename(string()) -> string(). tempfilename(Base) -> {MegaSecs, Secs, MicroSecs} = now(), Filename = io_lib:format("~s-~s-~p.~p", [Base, os:getpid(), MegaSecs * 1000000 + Secs, MicroSecs]), Filename. -spec fsync([string()]) -> ok. fsync(Paths) -> case fsyncport:fsyncall(Paths) of ok -> ok; {error, Error} -> exit_with_error(fsync, Error, "Error in fsync") end. -spec exit_with_error(atom(), atom(), string()) -> no_return(). exit_with_error(Operation, Error, ErrorMessage) -> io:format("~s(~w): ~w~n", [ErrorMessage, Operation, Error]), exit({fileerror, Operation, Error, ErrorMessage}). -spec check_error(any(), atom(), string()) -> ok. check_error(ReturnValue, Operation, ErrorMessage) -> case ReturnValue of ok -> ok; {error, Error} -> exit_with_error(Operation, Error, ErrorMessage) end. -spec write_tempfile_and_rename(string(), string(), binary()) -> ok. write_tempfile_and_rename(Name, NurseryName, Content) -> case file:open(NurseryName, [write, exclusive]) of {ok, File} -> ok = file:write(File, Content), file:close(File), check_error(file:rename(NurseryName, Name), rename, "Error when renaming tempfile to final file"); {error, eexist} -> %% Should not happen, file name should be unique exit_with_error(writefile, eexist, "File existed when creating tempfile"); {error, Error} -> exit_with_error(writefile, Error, "Error when creating tempfile") end. spawn_and_wait(Fun) -> ParentPid = self(), ChildPid = spawn_link(fun () -> try Result = Fun(), ParentPid ! {result, self(), Result} catch Type:What -> [CrashFunction | Stack] = erlang:get_stacktrace(), lager:error("Crashed process: ~p ~p~n ~p~n ~p~n", [Type, What, CrashFunction, Stack]), ParentPid ! {result, self(), crash} end end), receive {result, ChildPid, Result} -> Result end.