./ct_report/coverage/mongoose_cluster_id.COVER.html

1 -module(mongoose_cluster_id).
2
3 -include("mongoose.hrl").
4
5 -export([
6 start/0,
7 get_cached_cluster_id/0,
8 get_backend_cluster_id/0
9 ]).
10
11 % For testing purposes only
12 -export([clean_table/0]).
13
14 -ignore_xref([clean_table/0, get_backend_cluster_id/0]).
15
16 -record(mongoose_cluster_id, {key :: atom(), value :: cluster_id()}).
17 -type cluster_id() :: binary().
18 -type maybe_cluster_id() :: {ok, cluster_id()} | {error, any()}.
19 -type mongoose_backend() :: rdbms
20 | mnesia.
21
22 -spec start() -> maybe_cluster_id().
23 start() ->
24 74 init_mnesia_cache(),
25 74 Backend = which_backend_available(),
26 74 maybe_prepare_queries(Backend),
27 74 CachedRes = get_cached_cluster_id(),
28 74 BackendRes = get_backend_cluster_id(),
29 74 case {CachedRes, BackendRes} of
30 {{ok, ID}, {ok, ID}} ->
31 25 {ok, ID};
32 {{ok, ID}, {error, _}} ->
33 1 set_new_cluster_id(ID, Backend);
34 {{error, _}, {ok, ID}} ->
35 47 set_new_cluster_id(ID, mnesia);
36 {{error, _}, {error, _}} ->
37 1 make_and_set_new_cluster_id();
38 {{ok, CachedID}, {ok, BackendID}} ->
39
:-(
?LOG_ERROR(#{what => cluster_id_setup_conflict,
40 text => <<"Mnesia and Backend have different cluster IDs">>,
41
:-(
cached_id => CachedID, backend_id => BackendID}),
42
:-(
{error, conflict}
43 end.
44
45 %% Get cached version
46 -spec get_cached_cluster_id() -> maybe_cluster_id().
47 get_cached_cluster_id() ->
48 121 T = fun() -> mnesia:read(mongoose_cluster_id, cluster_id) end,
49 121 case mnesia:transaction(T) of
50 {atomic, [#mongoose_cluster_id{value = ClusterID}]} ->
51 73 {ok, ClusterID};
52 {atomic, []} ->
53 48 {error, cluster_id_not_in_mnesia};
54 {aborted, Reason} ->
55
:-(
{error, Reason}
56 end.
57
58 %% ====================================================================
59 %% Internal getters and setters
60 %% ====================================================================
61 -spec get_backend_cluster_id() -> maybe_cluster_id().
62 get_backend_cluster_id() ->
63 77 get_backend_cluster_id(which_backend_available()).
64
65 -spec set_new_cluster_id(cluster_id()) -> maybe_cluster_id().
66 set_new_cluster_id(ID) ->
67 1 set_new_cluster_id(ID, which_backend_available()).
68
69 -spec make_and_set_new_cluster_id() -> maybe_cluster_id().
70 make_and_set_new_cluster_id() ->
71 1 NewID = make_cluster_id(),
72 1 set_new_cluster_id(NewID).
73
74 %% ====================================================================
75 %% Internal functions
76 %% ====================================================================
77 init_mnesia_cache() ->
78 74 mnesia:create_table(mongoose_cluster_id,
79 [{type, set},
80 {record_name, mongoose_cluster_id},
81 {attributes, record_info(fields, mongoose_cluster_id)},
82 {ram_copies, [node()]}
83 ]),
84 74 mnesia:add_table_copy(mongoose_cluster_id, node(), ram_copies).
85
86 -spec maybe_prepare_queries(mongoose_backend()) -> ok.
87
:-(
maybe_prepare_queries(mnesia) -> ok;
88 maybe_prepare_queries(rdbms) ->
89 74 mongoose_rdbms:prepare(cluster_insert_new, mongoose_cluster_id, [v],
90 <<"INSERT INTO mongoose_cluster_id(k,v) VALUES ('cluster_id', ?)">>),
91 74 mongoose_rdbms:prepare(cluster_select, mongoose_cluster_id, [],
92 <<"SELECT v FROM mongoose_cluster_id WHERE k='cluster_id'">>),
93 74 ok.
94
95 -spec execute_cluster_insert_new(binary()) -> mongoose_rdbms:query_result().
96 execute_cluster_insert_new(ID) ->
97 2 mongoose_rdbms:execute_successfully(global, cluster_insert_new, [ID]).
98
99 -spec make_cluster_id() -> cluster_id().
100 make_cluster_id() ->
101 1 uuid:uuid_to_string(uuid:get_v4(), binary_standard).
102
103 %% Which backend is enabled
104 -spec which_backend_available() -> mongoose_backend().
105 which_backend_available() ->
106 153 case mongoose_wpool:get_pool_settings(rdbms, global, default) of
107
:-(
undefined -> mnesia;
108 153 _ -> rdbms
109 end.
110
111 -spec set_new_cluster_id(cluster_id(), mongoose_backend()) -> ok | {error, any()}.
112 set_new_cluster_id(ID, rdbms) ->
113 2 try execute_cluster_insert_new(ID) of
114 {updated, 1} ->
115 2 set_new_cluster_id(ID, mnesia),
116 2 {ok, ID}
117 catch
118 Class:Reason:Stacktrace ->
119
:-(
?LOG_WARNING(#{what => cluster_id_set_failed,
120 text => <<"Error inserting cluster ID into RDBMS">>,
121 cluster_id => ID,
122
:-(
class => Class, reason => Reason, stacktrace => Stacktrace}),
123
:-(
{error, {Class, Reason}}
124 end;
125 set_new_cluster_id(ID, mnesia) ->
126 49 T = fun() -> mnesia:write(#mongoose_cluster_id{key = cluster_id, value = ID}) end,
127 49 case mnesia:transaction(T) of
128 {atomic, ok} ->
129 49 {ok, ID};
130 {aborted, Reason} ->
131
:-(
{error, Reason}
132 end.
133
134 %% Get cluster ID
135 -spec get_backend_cluster_id(mongoose_backend()) -> maybe_cluster_id().
136 get_backend_cluster_id(rdbms) ->
137 77 try mongoose_rdbms:execute_successfully(global, cluster_select, []) of
138 74 {selected, [{ID}]} -> {ok, ID};
139 3 {selected, []} -> {error, no_value_in_backend}
140 catch
141 Class:Reason:Stacktrace ->
142
:-(
?LOG_WARNING(#{what => cluster_id_get_failed,
143 text => <<"Error getting cluster ID from RDBMS">>,
144
:-(
class => Class, reason => Reason, stacktrace => Stacktrace}),
145
:-(
{error, {Class, Reason}}
146 end;
147 get_backend_cluster_id(mnesia) ->
148
:-(
get_cached_cluster_id().
149
150 clean_table() ->
151 1 clean_table(which_backend_available()).
152
153 -spec clean_table(mongoose_backend()) -> ok | {error, any()}.
154 clean_table(rdbms) ->
155 1 SQLQuery = [<<"TRUNCATE TABLE mongoose_cluster_id;">>],
156 1 try mongoose_rdbms:sql_query(global, SQLQuery) of
157
:-(
{selected, _} -> ok;
158 1 {updated, _} -> ok;
159
:-(
{error, _} = Err -> Err
160 catch
161 Class:Reason:Stacktrace ->
162
:-(
?LOG_WARNING(#{what => cluster_id_clean_failed,
163 text => <<"Error truncating mongoose_cluster_id table">>,
164 sql_query => SQLQuery,
165
:-(
class => Class, reason => Reason, stacktrace => Stacktrace}),
166
:-(
{error, {Class, Reason}}
167 end;
168
:-(
clean_table(_) -> ok.
Line Hits Source