erlang自动编译与加载
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

235 line
8.2 KiB

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