erlang自动编译与加载
Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

236 rader
8.3 KiB

4 år sedan
4 år sedan
  1. -module(esSyncSrv).
  2. -behaviour(es_gen_ipc).
  3. %%%%%%%%%%%%%%%%%%%%%%%% eSync.hrl start %%%%%%%%%%%%%%%%%%%%%%
  4. -define(LOG_ON(Val), Val == true; Val == all; Val == skip_success; is_list(Val), Val =/= []).
  5. -define(Log, log).
  6. -define(compileCmd, compileCmd).
  7. -define(extraDirs, extraDirs).
  8. -define(descendant, descendant).
  9. -define(onMSyncFun, onMSyncFun).
  10. -define(onCSyncFun, onCSyncFun).
  11. -define(swSyncNode, swSyncNode).
  12. -define(isJustMem, isJustMem).
  13. -define(debugInfoKeyFun, debugInfoKeyFun).
  14. -define(DefCfgList, [{?Log, all}, {?compileCmd, undefined}, {?extraDirs, undefined}, {?descendant, fix}, {?onMSyncFun, undefined}, {?onCSyncFun, undefined}, {?swSyncNode, false}, {?isJustMem, false}, {?debugInfoKeyFun, undefined}]).
  15. -define(esCfgSync, esCfgSync).
  16. -define(rootSrcDir, <<"src">>).
  17. %%%%%%%%%%%%%%%%%%%%%%%% eSync.hrl end %%%%%%%%%%%%%%%%%%%%%%
  18. -compile(inline).
  19. -compile({inline_size, 128}).
  20. %% API
  21. -export([
  22. start_link/0,
  23. rescan/0,
  24. pause/0,
  25. unpause/0,
  26. setLog/1,
  27. getLog/0,
  28. curInfo/0,
  29. getOnMSync/0,
  30. setOnMSync/1,
  31. getOnCSync/0,
  32. setOnCSync/1,
  33. swSyncNode/1
  34. ]).
  35. %% es_gen_ipc callbacks
  36. -export([
  37. init/1,
  38. handleCall/4,
  39. handleAfter/3,
  40. handleCast/3,
  41. handleInfo/3,
  42. handleOnevent/4,
  43. terminate/3
  44. ]).
  45. -define(SERVER, ?MODULE).
  46. -define(None, 0).
  47. -record(state, {
  48. port = undefined
  49. , onMSyncFun = undefined
  50. , onCSyncFun = undefined
  51. , swSyncNode = false
  52. , srcFiles = #{} :: map()
  53. , hrlFiles = #{} :: map()
  54. , configs = #{} :: map()
  55. , beams = #{} :: map()
  56. }).
  57. %% ************************************ API start ***************************
  58. rescan() ->
  59. es_gen_ipc:cast(?SERVER, miRescan),
  60. esUtils:logSuccess("start rescaning source files..."),
  61. ok.
  62. unpause() ->
  63. es_gen_ipc:cast(?SERVER, miUnpause),
  64. ok.
  65. pause() ->
  66. es_gen_ipc:cast(?SERVER, miPause),
  67. esUtils:logSuccess("Pausing eSync. Call eSync:run() to restart"),
  68. ok.
  69. curInfo() ->
  70. es_gen_ipc:call(?SERVER, miCurInfo).
  71. setLog(T) when ?LOG_ON(T) ->
  72. esUtils:setEnv(log, T),
  73. esUtils:loadCfg(),
  74. esUtils:logSuccess("Console Notifications Enabled"),
  75. ok;
  76. setLog(_) ->
  77. esUtils:setEnv(log, none),
  78. esUtils:loadCfg(),
  79. esUtils:logSuccess("Console Notifications Disabled"),
  80. ok.
  81. getLog() ->
  82. ?esCfgSync:getv(log).
  83. swSyncNode(IsSync) ->
  84. es_gen_ipc:cast(?SERVER, {miSyncNode, IsSync}),
  85. ok.
  86. getOnMSync() ->
  87. es_gen_ipc:call(?SERVER, miGetOnMSync).
  88. setOnMSync(Fun) ->
  89. es_gen_ipc:call(?SERVER, {miSetOnMSync, Fun}).
  90. getOnCSync() ->
  91. es_gen_ipc:call(?SERVER, miGetOnCSync).
  92. setOnCSync(Fun) ->
  93. es_gen_ipc:call(?SERVER, {miSetOnCSync, Fun}).
  94. %% ************************************ API end ***************************
  95. start_link() ->
  96. es_gen_ipc:start_link({local, ?SERVER}, ?MODULE, ?None, []).
  97. %% status :: waiting | running | pause
  98. init(_Args) ->
  99. erlang:process_flag(trap_exit, true),
  100. esUtils:loadCfg(),
  101. {ok, waiting, #state{onMSyncFun = ?esCfgSync:getv(?onMSyncFun), onCSyncFun = ?esCfgSync:getv(?onCSyncFun), swSyncNode = ?esCfgSync:getv(?swSyncNode)}, {doAfter, ?None}}.
  102. handleAfter(?None, waiting, State) ->
  103. %% 启动port 发送监听目录信息
  104. PortName = esUtils:fileSyncPath("fileSync"),
  105. Opts = [{packet, 4}, binary, exit_status, use_stdio],
  106. Port = erlang:open_port({spawn_executable, PortName}, Opts),
  107. {kpS, State#state{port = Port}, {sTimeout, 4000, waitConnOver}}.
  108. handleCall(miGetOnMSync, _, #state{onMSyncFun = OnMSyncFun} = State, _From) ->
  109. {reply, OnMSyncFun, State};
  110. handleCall({miSetOnMSync, Fun}, _, State, _From) ->
  111. {reply, ok, State#state{onMSyncFun = Fun}};
  112. handleCall(miGetOnCSync, _, #state{onCSyncFun = OnCSyncFun} = State, _From) ->
  113. {reply, OnCSyncFun, State};
  114. handleCall({miSetOnCSync, Fun}, _, State, _From) ->
  115. {reply, ok, State#state{onCSyncFun = Fun}};
  116. handleCall(miCurInfo, Status, State, _Form) ->
  117. {reply, {Status, erlang:get(), State}, State};
  118. handleCall(_Request, _, _State, _From) ->
  119. kpS_S.
  120. handleCast(miPause, running, State) ->
  121. {nextS, pause, State};
  122. handleCast(miUnpause, pause, State) ->
  123. {nextS, running, State};
  124. handleCast({miSyncNode, IsSync}, _, State) ->
  125. case IsSync of
  126. true ->
  127. {kpS, State#state{swSyncNode = true}};
  128. _ ->
  129. {kpS, State#state{swSyncNode = false}}
  130. end;
  131. handleCast(miRescan, _, State) ->
  132. {Srcs, Hrls, Configs, Beams} = esUtils:collSrcFiles(false),
  133. {kpS_S, State#state{srcFiles = Srcs, hrlFiles = Hrls, configs = Configs, beams = Beams}};
  134. handleCast(_Msg, _, _State) ->
  135. kpS_S.
  136. handleInfo({Port, {data, Data}}, Status, #state{srcFiles = Srcs, hrlFiles = Hrls, configs = Configs, beams = Beams, onMSyncFun = OnMSyncFun, onCSyncFun = OnCSyncFun, swSyncNode = SwSyncNode} = State) ->
  137. case Status of
  138. running ->
  139. FileList = binary:split(Data, <<"\r\n">>, [global]),
  140. %% 收集改动了beam hrl src 文件 然后执行相应的逻辑
  141. {CBeams, CConfigs, CHrls, CSrcs, NewSrcs, NewHrls, NewConfigs, NewBeams} = esUtils:classifyChangeFile(FileList, [], [], #{}, #{}, Srcs, Hrls, Configs, Beams),
  142. esUtils:fireOnSync(OnCSyncFun, CConfigs),
  143. esUtils:reloadChangedMod(CBeams, SwSyncNode, OnMSyncFun, []),
  144. case ?esCfgSync:getv(?compileCmd) of
  145. undefined ->
  146. LastCHrls = esUtils:collIncludeCHrls(maps:keys(CHrls), NewHrls, CHrls, #{}),
  147. NReSrcs = esUtils:collIncludeCErls(maps:keys(LastCHrls), NewSrcs, CSrcs, #{}),
  148. esUtils:recompileChangeSrcFile(maps:iterator(NReSrcs), SwSyncNode),
  149. {kpS, State#state{srcFiles = NewSrcs, hrlFiles = NewHrls, configs = NewConfigs, beams = NewBeams}};
  150. CmdStr ->
  151. case maps:size(CSrcs) > 0 orelse CHrls =/= [] of
  152. true ->
  153. RetStr = os:cmd(CmdStr),
  154. RetList = string:split(RetStr, "\n", all),
  155. esUtils:logSuccess("compile cmd:~p ~n", [CmdStr]),
  156. esUtils:logSuccess("the result: ~n ", []),
  157. [
  158. begin
  159. esUtils:logSuccess("~p ~n", [OneRet])
  160. end || OneRet <- RetList, OneRet =/= []
  161. ],
  162. ok;
  163. _ ->
  164. ignore
  165. end,
  166. kpS_S
  167. end;
  168. _ ->
  169. case Data of
  170. <<"init">> ->
  171. %% port启动成功 先发送监听目录配置
  172. {AddSrcDirs, OnlySrcDirs, DelSrcDirs} = esUtils:mergeExtraDirs(false),
  173. AddStr = string:join([filename:nativename(OneDir) || OneDir <- AddSrcDirs], "|"),
  174. OnlyStr = string:join([filename:nativename(OneDir) || OneDir <- OnlySrcDirs], "|"),
  175. DelStr = string:join([filename:nativename(OneDir) || OneDir <- DelSrcDirs], "|"),
  176. AllStr = string:join([AddStr, OnlyStr, DelStr], "\r\n"),
  177. erlang:port_command(Port, AllStr),
  178. esUtils:logSuccess("eSync connect fileSync success..."),
  179. %% 然后收集一下监听目录下的src文件
  180. {BSrcs, BHrls, BConfigs, BBeams} = esUtils:collSrcFiles(true),
  181. {nextS, running, State#state{srcFiles = BSrcs, hrlFiles = BHrls, configs = BConfigs, beams = BBeams}, {isHib, true}};
  182. _ ->
  183. esUtils:logErrors("error, esSyncSrv receive unexpect port msg ~p~n", [Data]),
  184. kpS_S
  185. end
  186. end;
  187. handleInfo({Port, closed}, running, #state{port = Port} = _State) ->
  188. esUtils:logErrors("esSyncSrv receive port closed ~n"),
  189. {nextS, port_close, _State};
  190. handleInfo({'EXIT', Port, Reason}, running, #state{port = Port} = _State) ->
  191. esUtils:logErrors("esSyncSrv receive port exit Reason:~p ~n", [Reason]),
  192. {nextS, {port_EXIT, Reason}, _State};
  193. handleInfo({Port, {exit_status, Status}}, running, #state{port = Port} = _State) ->
  194. esUtils:logErrors("esSyncSrv receive port exit_status Status:~p ~p ~n", [Status, Port]),
  195. {nextS, {port_exit_status, Status}, _State};
  196. handleInfo({'EXIT', _Pid, _Reason}, running, _State) ->
  197. kpS_S;
  198. handleInfo(_Msg, _, _State) ->
  199. esUtils:logErrors("esSyncSrv receive unexpect msg:~p ~n", [_Msg]),
  200. kpS_S.
  201. handleOnevent(sTimeout, waitConnOver, Status, State) ->
  202. esUtils:logErrors("failed to connect the fileSync to stop stauts:~p state:~p ~n", [Status, State]),
  203. stop;
  204. handleOnevent(_EventType, _EventContent, _Status, _State) ->
  205. kpS_S.
  206. terminate(_Reason, _Status, _State) ->
  207. ok.