From ef456ab64591d20c8704f2c674415cc93d87f09c Mon Sep 17 00:00:00 2001 From: Alexey Shchepin Date: Fri, 27 Jan 2006 05:02:33 +0000 Subject: [PATCH] * src/ejabberd_update.erl: Support for run-time ejabberd updating (not completed) * src/ejabberd_c2s.erl: Added 'update_info' module attribute for testing ejabberd_update SVN Revision: 494 --- src/ejabberd_update.erl | 113 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100644 src/ejabberd_update.erl diff --git a/src/ejabberd_update.erl b/src/ejabberd_update.erl new file mode 100644 index 000000000..103b20509 --- /dev/null +++ b/src/ejabberd_update.erl @@ -0,0 +1,113 @@ +%%%------------------------------------------------------------------- +%%% File : ejabberd_update.erl +%%% Author : Alexey Shchepin +%%% Purpose : Update ejabberd +%%% Created : 27 Jan 2006 by Alexey Shchepin +%%% Id : $Id: ejabberd_c2s.erl 492 2006-01-25 00:35:12Z alexey $ +%%%------------------------------------------------------------------- + +-module(ejabberd_update). +-author('alexey@sevcom.net'). + +%% API +-export([update/0]). + +%%==================================================================== +%% API +%%==================================================================== +update() -> + Dir = filename:dirname(code:which(ejabberd)), + case file:list_dir(Dir) of + {ok, Files} -> + Beams = [list_to_atom(filename:rootname(FN)) || + FN <- Files, lists:suffix(".beam", FN)], + UpdatedBeams = + lists:filter( + fun(Module) -> + {ok, {Module, [NewVsn]}} = + beam_lib:version(code:which(Module)), + case code:is_loaded(Module) of + {file, _} -> + Attrs = Module:module_info(attributes), + {value, {vsn, [CurVsn]}} = + lists:keysearch(vsn, 1, Attrs), + NewVsn /= CurVsn; + false -> + false + end + end, Beams), + io:format("beam files: ~p~n", [UpdatedBeams]), + Script = make_script(UpdatedBeams), + io:format("script: ~p~n", [Script]), + LowLevelScript = make_low_level_script(UpdatedBeams, Script), + io:format("low level script: ~p~n", [LowLevelScript]), + Check = + release_handler_1:check_script( + LowLevelScript, + [{ejabberd, "", filename:join(Dir, "..")}]), + io:format("check: ~p~n", [Check]), + Eval = + release_handler_1:eval_script( + LowLevelScript, [], + [{ejabberd, "", filename:join(Dir, "..")}]), + io:format("eval: ~p~n", [Eval]); + {error, Reason} -> + {error, Reason} + end. + + +%%-------------------------------------------------------------------- +%%% Internal functions +%%-------------------------------------------------------------------- + +%% From systools.hrl +-record(application, + {name, %% Name of the application, atom(). + type = permanent, %% Application start type, atom(). + vsn = "", %% Version of the application, string(). + id = "", %% Id of the application, string(). + description = "", %% Description of application, string(). + modules = [], %% [Module | {Module,Vsn}] of modules + %% incorporated in the application, + %% Module = atom(), Vsn = string(). + uses = [], %% [Application] list of applications required + %% by the application, Application = atom(). + includes = [], %% [Application] list of applications included + %% by the application, Application = atom(). + regs = [], %% [RegNames] a list of registered process + %% names used by the application, RegNames = + %% atom(). + env = [], %% [{Key,Value}] environment variable of + %% application, Key = Value = term(). + maxT = infinity, %% Max time an application may exist, + %% integer() | infinity. + maxP = infinity, %% Max number of processes in an application, + %% integer() | infinity. + mod = [], %% [] | {Mod, StartArgs}, Mod= atom(), + %% StartArgs = list(). + start_phases = [], %% [] | {Phase, PhaseArgs}, Phase = atom(), + %% PhaseArgs = list(). + dir = "" %% The directory where the .app file was + %% found (internal use). + }). + + +make_script(UpdatedBeams) -> + lists:map( + fun(Module) -> + {ok, {Module, [{attributes, Attrs}]}} = + beam_lib:chunks(code:which(Module), [attributes]), + case lists:keysearch(update_info, 1, Attrs) of + {value, {_, [{update, Extra}]}} -> + {update, Module, {advanced, Extra}}; + false -> + {load_module, Module} + end + end, UpdatedBeams). + +make_low_level_script(UpdatedBeams, Script) -> + EJDApp = #application{name = ejabberd, + modules = UpdatedBeams}, + {ok, LowLevelScript} = + systools_rc:translate_scripts([Script], [EJDApp], [EJDApp]), + LowLevelScript.