fix mnesia
This commit is contained in:
parent
b8d3d4b524
commit
634a3ece75
@ -14,8 +14,8 @@ start(_StartType, _StartArgs) ->
|
|||||||
%% 加速内存的回收
|
%% 加速内存的回收
|
||||||
erlang:system_flag(fullsweep_after, 16),
|
erlang:system_flag(fullsweep_after, 16),
|
||||||
try
|
try
|
||||||
%% 启动mnesia数据库
|
%% 启动并校验已经初始化好的 mnesia 数据库
|
||||||
start_mnesia(),
|
ok = iot_mnesia:start(),
|
||||||
|
|
||||||
%% 启动http服务。当前 supervisor 初始化依赖本机 simulator API,因此保留此顺序。
|
%% 启动http服务。当前 supervisor 初始化依赖本机 simulator API,因此保留此顺序。
|
||||||
start_http_server(),
|
start_http_server(),
|
||||||
@ -43,17 +43,6 @@ stop(_State) ->
|
|||||||
|
|
||||||
%% internal functions
|
%% internal functions
|
||||||
|
|
||||||
%% 启动内存数据库
|
|
||||||
start_mnesia() ->
|
|
||||||
ok = ensure_mnesia_schema(),
|
|
||||||
%% 启动数据库
|
|
||||||
ok = mnesia:start(),
|
|
||||||
ok = ensure_mnesia_tables(),
|
|
||||||
Tables = mnesia:system_info(tables),
|
|
||||||
logger:debug("[iot_app] tables: ~p", [Tables]),
|
|
||||||
%% 创建数据库表
|
|
||||||
ok.
|
|
||||||
|
|
||||||
start_http_server() ->
|
start_http_server() ->
|
||||||
{ok, Props} = application:get_env(iot, http_server),
|
{ok, Props} = application:get_env(iot, http_server),
|
||||||
Acceptors = proplists:get_value(acceptors, Props, 50),
|
Acceptors = proplists:get_value(acceptors, Props, 50),
|
||||||
@ -113,37 +102,5 @@ start_ssl_server() ->
|
|||||||
stop_started_services() ->
|
stop_started_services() ->
|
||||||
_ = cowboy:stop_listener(http_listener),
|
_ = cowboy:stop_listener(http_listener),
|
||||||
_ = ranch:stop_listener(ssl_server),
|
_ = ranch:stop_listener(ssl_server),
|
||||||
_ = mnesia:stop(),
|
_ = iot_mnesia:stop(),
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
-spec ensure_mnesia_schema() -> any().
|
|
||||||
ensure_mnesia_schema() ->
|
|
||||||
case mnesia:system_info(use_dir) of
|
|
||||||
true ->
|
|
||||||
ok;
|
|
||||||
false ->
|
|
||||||
mnesia:stop(),
|
|
||||||
case mnesia:create_schema([node()]) of
|
|
||||||
ok -> ok;
|
|
||||||
{error, {_, {already_exists, _}}} -> ok;
|
|
||||||
Error ->
|
|
||||||
logger:debug("[iot_app] create mnesia schema failed with error: ~p", [Error]),
|
|
||||||
throw({init_schema, Error})
|
|
||||||
end
|
|
||||||
end.
|
|
||||||
|
|
||||||
-spec ensure_mnesia_tables() -> ok.
|
|
||||||
ensure_mnesia_tables() ->
|
|
||||||
ok = ensure_efka_client_table(),
|
|
||||||
ok = mnesia:wait_for_tables([efka_client], 5000),
|
|
||||||
ok.
|
|
||||||
|
|
||||||
-spec ensure_efka_client_table() -> ok.
|
|
||||||
ensure_efka_client_table() ->
|
|
||||||
case efka_client_store:ensure_table() of
|
|
||||||
ok ->
|
|
||||||
ok;
|
|
||||||
{error, Reason} ->
|
|
||||||
logger:debug("[iot_app] create efka_client table failed with error: ~p", [Reason]),
|
|
||||||
throw({init_tables, {efka_client, Reason}})
|
|
||||||
end.
|
|
||||||
132
src/mnesia/iot_mnesia.erl
Normal file
132
src/mnesia/iot_mnesia.erl
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
%%%-------------------------------------------------------------------
|
||||||
|
%%% @doc Mnesia bootstrap and runtime startup helpers.
|
||||||
|
%%%
|
||||||
|
%%% `init/0` is a manual, one-time bootstrap operation. Application
|
||||||
|
%%% startup must call `start/0`, which only starts an existing schema and
|
||||||
|
%%% verifies required tables.
|
||||||
|
%%%-------------------------------------------------------------------
|
||||||
|
-module(iot_mnesia).
|
||||||
|
|
||||||
|
-include("iot_tables.hrl").
|
||||||
|
|
||||||
|
-export([init/0, start/0, stop/0]).
|
||||||
|
|
||||||
|
-define(TABLES, [efka_client]).
|
||||||
|
-define(WAIT_TIMEOUT, 5000).
|
||||||
|
|
||||||
|
-spec init() -> ok | {error, term()}.
|
||||||
|
init() ->
|
||||||
|
with_result(fun() ->
|
||||||
|
ok = ensure_persistent_dir(),
|
||||||
|
_ = mnesia:stop(),
|
||||||
|
ok = create_schema_if_missing(),
|
||||||
|
ok = start_mnesia(),
|
||||||
|
ok = create_tables(),
|
||||||
|
ok = wait_for_tables(),
|
||||||
|
ok = stop(),
|
||||||
|
ok
|
||||||
|
end).
|
||||||
|
|
||||||
|
-spec start() -> ok | {error, term()}.
|
||||||
|
start() ->
|
||||||
|
with_result(fun() ->
|
||||||
|
ok = ensure_persistent_dir(),
|
||||||
|
ok = start_mnesia(),
|
||||||
|
ok = wait_for_tables(),
|
||||||
|
ok = verify_tables(),
|
||||||
|
log_runtime_info(),
|
||||||
|
ok
|
||||||
|
end).
|
||||||
|
|
||||||
|
-spec stop() -> ok.
|
||||||
|
stop() ->
|
||||||
|
_ = mnesia:stop(),
|
||||||
|
ok.
|
||||||
|
|
||||||
|
-spec ensure_persistent_dir() -> ok.
|
||||||
|
ensure_persistent_dir() ->
|
||||||
|
case mnesia:system_info(use_dir) of
|
||||||
|
true ->
|
||||||
|
ok;
|
||||||
|
false ->
|
||||||
|
throw({mnesia_dir_required, node()})
|
||||||
|
end.
|
||||||
|
|
||||||
|
-spec create_schema_if_missing() -> ok.
|
||||||
|
create_schema_if_missing() ->
|
||||||
|
case mnesia:create_schema([node()]) of
|
||||||
|
ok ->
|
||||||
|
ok;
|
||||||
|
{error, {_, {already_exists, _}}} ->
|
||||||
|
ok;
|
||||||
|
{error, Reason} ->
|
||||||
|
throw({create_schema_failed, Reason})
|
||||||
|
end.
|
||||||
|
|
||||||
|
-spec start_mnesia() -> ok.
|
||||||
|
start_mnesia() ->
|
||||||
|
case mnesia:start() of
|
||||||
|
ok ->
|
||||||
|
ok;
|
||||||
|
{error, {already_started, mnesia}} ->
|
||||||
|
ok;
|
||||||
|
{error, Reason} ->
|
||||||
|
throw({start_mnesia_failed, Reason})
|
||||||
|
end.
|
||||||
|
|
||||||
|
-spec create_tables() -> ok.
|
||||||
|
create_tables() ->
|
||||||
|
case efka_client_store:ensure_table() of
|
||||||
|
ok ->
|
||||||
|
ok;
|
||||||
|
{error, Reason} ->
|
||||||
|
throw({create_table_failed, {efka_client, Reason}})
|
||||||
|
end.
|
||||||
|
|
||||||
|
-spec wait_for_tables() -> ok.
|
||||||
|
wait_for_tables() ->
|
||||||
|
case mnesia:wait_for_tables(?TABLES, ?WAIT_TIMEOUT) of
|
||||||
|
ok ->
|
||||||
|
ok;
|
||||||
|
{timeout, Tables} ->
|
||||||
|
throw({mnesia_tables_timeout, Tables});
|
||||||
|
{error, Reason} ->
|
||||||
|
throw({mnesia_tables_error, Reason})
|
||||||
|
end.
|
||||||
|
|
||||||
|
-spec verify_tables() -> ok.
|
||||||
|
verify_tables() ->
|
||||||
|
lists:foreach(fun verify_table/1, ?TABLES),
|
||||||
|
ok.
|
||||||
|
|
||||||
|
-spec verify_table(atom()) -> ok.
|
||||||
|
verify_table(efka_client) ->
|
||||||
|
Expected = record_info(fields, efka_client),
|
||||||
|
case mnesia:table_info(efka_client, attributes) of
|
||||||
|
Expected ->
|
||||||
|
ok;
|
||||||
|
Actual ->
|
||||||
|
throw({table_attributes_mismatch, efka_client, Expected, Actual})
|
||||||
|
end.
|
||||||
|
|
||||||
|
-spec log_runtime_info() -> ok.
|
||||||
|
log_runtime_info() ->
|
||||||
|
logger:debug("[iot_mnesia] node: ~p, dir: ~p, tables: ~p", [
|
||||||
|
node(),
|
||||||
|
mnesia:system_info(directory),
|
||||||
|
mnesia:system_info(tables)
|
||||||
|
]),
|
||||||
|
ok.
|
||||||
|
|
||||||
|
-spec with_result(fun(() -> ok)) -> ok | {error, term()}.
|
||||||
|
with_result(Fun) ->
|
||||||
|
try Fun() of
|
||||||
|
ok ->
|
||||||
|
ok
|
||||||
|
catch
|
||||||
|
throw:Reason ->
|
||||||
|
{error, Reason};
|
||||||
|
Class:Reason:Stacktrace ->
|
||||||
|
logger:warning("[iot_mnesia] failed, class: ~p, reason: ~p, stack: ~p", [Class, Reason, Stacktrace]),
|
||||||
|
{error, Reason}
|
||||||
|
end.
|
||||||
@ -161,8 +161,9 @@ handle_info(Info, State) ->
|
|||||||
logger:warning("[ssl_channel] get a unknown message: ~p, state: ~p", [Info, State]),
|
logger:warning("[ssl_channel] get a unknown message: ~p, state: ~p", [Info, State]),
|
||||||
{noreply, State}.
|
{noreply, State}.
|
||||||
|
|
||||||
terminate(Reason, #state{inflight = Inflight}) ->
|
terminate(Reason, #state{inflight = Inflight, transport = Transport, socket = Socket}) ->
|
||||||
maps:foreach(fun(Ref, CommandInfo) -> reply_command_closed(Ref, CommandInfo, Reason) end, Inflight),
|
maps:foreach(fun(Ref, CommandInfo) -> reply_command_closed(Ref, CommandInfo, Reason) end, Inflight),
|
||||||
|
Transport:close(Socket),
|
||||||
logger:warning("[ssl_channel] stop with reason: ~p", [Reason]),
|
logger:warning("[ssl_channel] stop with reason: ~p", [Reason]),
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user