Safe Insert , to avoid the 2GB table limit on mnesia.
parent
0cf55ca2ec
commit
ea942d56f0
|
@ -19,7 +19,7 @@ erl_crash.dump
|
|||
*.d
|
||||
|
||||
# File temporanei di Mnesia (database locale)
|
||||
Mnesia.*
|
||||
mnesia.*
|
||||
|
||||
# File temporanei di editor
|
||||
*~
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
%% db_safe_insert.hrl
|
||||
|
||||
-record(global_message, {id, activity, timestamp}).
|
||||
-record(ap_users, {id, name, email, created_at}).
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -10,8 +10,8 @@
|
|||
start(_Type, _Args) ->
|
||||
|
||||
%% creiamo un utente di test, solo per vedere se mnesia va
|
||||
user_db:init(),
|
||||
timeline_db:init(),
|
||||
db_organization:setup(),
|
||||
db_organization:init(),
|
||||
users_local_check:check_ENV(), %% controlla le variabili d'ambiente
|
||||
|
||||
%% aggiungiamo un paio di utenti di esempio.
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
-module(db_organization).
|
||||
-export([setup/0, init/0]).
|
||||
|
||||
%% 1. Imposta la directory di Mnesia leggendo la variabile di ambiente
|
||||
setup() ->
|
||||
case os:getenv("AP_DB_DIR") of
|
||||
false ->
|
||||
io:format("Errore: la variabile di ambiente AP_DB_DIR non è settata!~n"),
|
||||
erlang:halt(1);
|
||||
Dir ->
|
||||
ok = application:set_env(mnesia, dir, Dir),
|
||||
ok
|
||||
end.
|
||||
|
||||
%% 2. Crea lo schema, avvia Mnesia e crea le tabelle (solo se non esistono già)
|
||||
init() ->
|
||||
%% Crea lo schema solo se non esiste già
|
||||
case mnesia:create_schema([node()]) of
|
||||
{error, {already_exists, _}} -> ok;
|
||||
_ -> ok
|
||||
end,
|
||||
%% Avvia Mnesia
|
||||
mnesia:start(),
|
||||
%% Crea tutte le tabelle
|
||||
create_tables().
|
||||
|
||||
%% 3. Crea tutte le tabelle che servono
|
||||
create_tables() ->
|
||||
create_table(ap_users, [id, name, email, created_at]),
|
||||
create_table(global_message, [id, activity, timestamp]).
|
||||
|
||||
%% Funzione helper per creare una tabella solo se non esiste già
|
||||
create_table(Name, Attributes) ->
|
||||
case mnesia:create_table(Name, [
|
||||
{disc_only_copies, [node()]},
|
||||
{attributes, Attributes}
|
||||
]) of
|
||||
{atomic, ok} ->
|
||||
io:format("Tabella ~p creata.~n", [Name]),
|
||||
ok;
|
||||
{aborted, {already_exists, _}} ->
|
||||
io:format("Tabella ~p già esistente.~n", [Name]),
|
||||
ok;
|
||||
Other ->
|
||||
io:format("Errore nella creazione della tabella ~p: ~p~n", [Name, Other]),
|
||||
erlang:halt(1)
|
||||
end.
|
|
@ -0,0 +1,32 @@
|
|||
-module(db_safe_insert).
|
||||
-include_lib("include/db_safe_insert.hrl").
|
||||
-export([safe_insert/2]).
|
||||
|
||||
safe_insert(Tab, Record) ->
|
||||
case mnesia:transaction(fun() -> mnesia:write(Record) end) of
|
||||
{atomic, ok} ->
|
||||
ok;
|
||||
{aborted, {file_size, _}} ->
|
||||
cleanup_and_retry(Tab, Record);
|
||||
{aborted, {no_disk_space, _}} ->
|
||||
cleanup_and_retry(Tab, Record);
|
||||
Other ->
|
||||
Other
|
||||
end.
|
||||
|
||||
cleanup_and_retry(Tab, Record) ->
|
||||
remove_oldest(Tab, 0.2),
|
||||
mnesia:transaction(fun() -> mnesia:write(Record) end).
|
||||
|
||||
remove_oldest(Tab, Fraction) ->
|
||||
Records = mnesia:dirty_match_object(make_pattern(Tab)),
|
||||
N = trunc(length(Records) * Fraction),
|
||||
Sorted = lists:sort(fun(A, B) -> get_timestamp(A) =< get_timestamp(B) end, Records),
|
||||
ToDelete = lists:sublist(Sorted, N),
|
||||
lists:foreach(fun(Rec) -> mnesia:dirty_delete_object(Rec) end, ToDelete).
|
||||
|
||||
make_pattern(global_message) -> #global_message{id='_', activity='_', timestamp='_'};
|
||||
make_pattern(ap_users) -> #ap_users{id='_', name='_', email='_', created_at='_'}. %% <-- PUNTO QUI DIOCANE!
|
||||
|
||||
get_timestamp(#global_message{timestamp=T}) -> T;
|
||||
get_timestamp(#ap_users{created_at=T}) -> T. %% <-- PUNTO SOLO ALLA FINE, DIOCANE!
|
|
@ -1,24 +1,15 @@
|
|||
%% timeline_db.erl
|
||||
-module(timeline_db).
|
||||
-export([init/0, add_message/1, all_messages/0]).
|
||||
-export([add_message/1, all_messages/0]).
|
||||
|
||||
-record(global_message, {id, activity, timestamp}).
|
||||
|
||||
init() ->
|
||||
%% Crea la tabella Mnesia se non esiste
|
||||
mnesia:create_table(global_message, [
|
||||
{attributes, record_info(fields, global_message)},
|
||||
{disc_copies, [node()]}
|
||||
]).
|
||||
|
||||
add_message(Activity) ->
|
||||
%% Crea un ID unico e un timestamp per il messaggio
|
||||
Id = erlang:unique_integer([monotonic, positive]),
|
||||
Timestamp = erlang:system_time(microsecond),
|
||||
F = fun() ->
|
||||
mnesia:write(#global_message{id=Id, activity=Activity, timestamp=Timestamp})
|
||||
end,
|
||||
mnesia:transaction(F).
|
||||
Record = #global_message{id=Id, activity=Activity, timestamp=Timestamp},
|
||||
db_safe_insert:safe_insert(global_message, Record).
|
||||
|
||||
all_messages() ->
|
||||
F = fun() ->
|
||||
|
|
|
@ -1,25 +1,16 @@
|
|||
-module(user_db).
|
||||
-export([init/0, add_user/2, get_user/1, all_users/0]).
|
||||
-include("db_safe_insert.hrl").
|
||||
-export([add_user/2, get_user/1, all_users/0]).
|
||||
|
||||
-record(user, {username, data}).
|
||||
add_user(Name, Email) ->
|
||||
Id = erlang:unique_integer([monotonic, positive]),
|
||||
Timestamp = erlang:system_time(microsecond),
|
||||
Record = #ap_users{id=Id, name=Name, email=Email, created_at=Timestamp},
|
||||
db_safe_insert:safe_insert(ap_users, Record).
|
||||
|
||||
init() ->
|
||||
mnesia:create_schema([node()]),
|
||||
mnesia:start(),
|
||||
mnesia:create_table(user, [
|
||||
{attributes, record_info(fields, user)},
|
||||
{disc_copies, [node()]}
|
||||
]).
|
||||
|
||||
add_user(Username, Data) ->
|
||||
get_user(Id) ->
|
||||
F = fun() ->
|
||||
mnesia:write(#user{username=Username, data=Data})
|
||||
end,
|
||||
mnesia:transaction(F).
|
||||
|
||||
get_user(Username) ->
|
||||
F = fun() ->
|
||||
case mnesia:read({user, Username}) of
|
||||
case mnesia:read({ap_users, Id}) of
|
||||
[User] -> {ok, User};
|
||||
[] -> not_found
|
||||
end
|
||||
|
@ -29,7 +20,8 @@ get_user(Username) ->
|
|||
|
||||
all_users() ->
|
||||
F = fun() ->
|
||||
mnesia:match_object(#user{username='_', data='_'})
|
||||
mnesia:match_object(#ap_users{id='_', name='_', email='_', created_at='_'})
|
||||
end,
|
||||
{atomic, Users} = mnesia:transaction(F),
|
||||
Users.
|
||||
|
||||
|
|
Loading…
Reference in New Issue