erlc $(erlc_params)
# Module pour la mise à jour de la BD
-$(rep_ebin)/euphorik_bd_admin.beam: $(rep_erl)/euphorik_bd_admin.erl $(rep_erl)/euphorik_bd.erl $(rep_include)/euphorik_bd.hrl $(rep_include)/euphorik_defines.hrl
+$(rep_ebin)/euphorik_bd_admin.beam: $(rep_erl)/euphorik_bd_admin.erl $(rep_include)/euphorik_bd.hrl $(rep_include)/euphorik_defines.hrl
erlc $(erlc_params)
# Module permettant l'extraction des conversations du minichat
# erlc $(erlc_params)
# Module effectuant periodiquement certaines tâches
-$(rep_ebin)/euphorik_daemon.beam: $(rep_erl)/euphorik_daemon.erl $(rep_include)/euphorik_defines.hrl $(rep_erl)/euphorik_bd_admin.erl
+$(rep_ebin)/euphorik_daemon.beam: $(rep_erl)/euphorik_daemon.erl $(rep_include)/euphorik_defines.hrl
erlc $(erlc_params)
# Module avec plein de bordel dedant
erlc $(erlc_params)
# Module dédié au tests
-$(rep_ebin)/euphorik_test.beam: $(rep_erl)/euphorik_test.erl $(rep_erl)/euphorik_bd.erl $(rep_include)/euphorik_bd.hrl
+$(rep_ebin)/euphorik_test.beam: $(rep_erl)/euphorik_test.erl $(rep_include)/euphorik_bd.hrl
erlc $(erlc_params)
# Suppression des modules compilés
nouveau_message(Mess, Auteur_id, Repond_A_ids) ->\r
% regarde si les id 'Repond_A' existent\r
F = fun() -> \r
- Repond_a = lists:map(\r
- fun(Repond_a_id) ->\r
- [M] = mnesia:read({minichat, Repond_a_id}),\r
- M\r
- end,\r
+ Repond_a = lists:foldr(\r
+ fun(Repond_a_id, Acc) ->\r
+ case mnesia:read({minichat, Repond_a_id}) of
+ [M] -> [M | Acc];\r
+ _ -> Acc % le message n'est pas trouvé
+ end\r
+ end,
+ [],\r
Repond_A_ids\r
- ), \r
+ ),\r
Racine_id = case Repond_a of\r
[] -> undefined;\r
[M | _] -> \r
_ ->\r
{erreur, "Les messages ne font pas partie de la même conversation"}\r
end\r
- end,\r
- case Racine_id of\r
- {erreur, E} -> {erreur, E};\r
- _ ->\r
- % est-ce que l'auteur existe ?\r
- case mnesia:wread({user, Auteur_id}) of\r
- [#user{profile = Profile} = Auteur] ->\r
- if length(Repond_a) =/= length(Repond_A_ids) ->\r
- {erreur, "Un ou plusieurs messages introuvable"};\r
- true ->\r
+ end,
+ if length(Repond_a) =/= length(Repond_A_ids) ->
+ {erreur, "Un ou plusieurs messages introuvable"};
+ true ->\r
+ case Racine_id of\r
+ {erreur, E} -> {erreur, E};\r
+ _ ->\r
+ % est-ce que l'auteur existe ?\r
+ case mnesia:wread({user, Auteur_id}) of\r
+ [#user{profile = Profile} = Auteur] ->\r
% comparaison entre la date du dernier poste et maintenant (gestion du flood)\r
Now = now(),\r
Delta = euphorik_common:delta_date_ms(Auteur#user.date_derniere_connexion, Now),\r
racine_id = if Racine_id =:= undefined -> Id; true -> Racine_id end\r
}),\r
Id\r
- end\r
- end;\r
- _ ->\r
- {erreur, "L'auteur du message est introuvable"}\r
- end\r
+ end;\r
+ _ ->\r
+ {erreur, "L'auteur du message est introuvable"}\r
+ end\r
+ end
end\r
end,\r
resultat_transaction(mnesia:transaction(F)).\r
messages(N, 1).\r
\r
\r
-% Renvoie N messages se trouvant sur la page P\r
+% Renvoie N messages se trouvant sur la page P
+% TODO FIXME : fonction en O(N * P) !\r
messages(N, P) ->\r
- F = fun() ->\r
- C = cursor(\r
- qlc:keysort(\r
- #minichat.id, \r
- q([E#minichat{contenu = contenu_message(E)} || E <- mnesia:table(minichat)]),\r
- [{order, descending}]\r
- ),\r
- [{tmpdir, ?KEY_SORT_TEMP_DIR}]\r
- ),\r
- if P > 1 -> qlc:next_answers(C, N * (P - 1));\r
- true -> ok\r
- end,\r
- R = qlc:next_answers(C, N),\r
- qlc:delete_cursor(C),\r
- R\r
+ F = fun() ->
+ % % #minichat{contenu = contenu_message(E)}
+ get_tuples_avant(minichat, reculer(minichat, mnesia:last(minichat), N * (P - 1)), N) \r
end,\r
- lists:reverse(resultat_transaction(mnesia:transaction(F))).\r
-\r
+ resultat_transaction(mnesia:transaction(F)).
+
+get_tuples_avant(Table, Id, N) ->
+ get_tuples_avant(Table, Id, N, []).
+get_tuples_avant(_, '$end_of_table', _, Tuples) -> Tuples;
+get_tuples_avant(_, _, 0, Tuples) ->
+ Tuples;
+get_tuples_avant(Table, Id, N, Tuples) ->
+ [T] = mnesia:read({Table, Id}),
+ get_tuples_avant(Table, mnesia:prev(Table, Id), N - 1, [T | Tuples]).
+
+reculer(_, '$end_of_table' = Fin, _) -> Fin;
+reculer(_, Id, 0) -> Id;
+reculer(Table, Id, N) ->
+ reculer(Table, mnesia:prev(Table, Id), N - 1).
+ \r
\r
% Renvoie les messages manquants pour la page P en sachant qu'il y a N message\r
% par page et que le dernier message que l'on possède est Id\r
{disc_copies, [node()]}
]),
mnesia:create_table(minichat, [
+ {type, ordered_set},
{attributes, record_info(fields, minichat)},
{disc_copies, [node()]}
]),
-module(euphorik_test).
-export([
+ bench_write_minichat/1,
start/2,
stop/1,
bench_get_messages/0,
-define(INTERVALLE_MIN, 2).\r
-define(INTERVALLE_MAX, 5).
+
% N est le nombre d'utilisateur
% M est le nombre de message que chaque utilisateur va poster
start(N, M) ->
stop(Pids) ->
lists:foreach(fun(Pid) -> exit(Pid, kill) end, Pids).
-
+% des trucs qui trainent
bench_get_messages() ->
T = [
{page,"chat"},
{conversations,{array,[]}}
],
moyenne_temps(euphorik_protocole, wait_event, [T], 20).
-
-
bench_get_messages_avec_2_conversations() ->
T = [
{page,"chat"},
]}}
],
moyenne_temps(euphorik_protocole, wait_event, [T], 20).
-
-
moyenne_temps(Module, Fun, Args, N) ->
moyenne_temps(Module, Fun, Args, N, N, 0).
moyenne_temps(_, _, _, 0, Total, Temps_acc) ->
% Tire au hasard de 0 à 3 messages sur les 10 derniers postés, renvoie une liste de int()
% répartition :
% 0 : 0.1
-% 1 : 0.7
-% 2 : 0.15
-% 3 : 0.05
+% 1 : 0.95
+% 2 : 0.04
+% 3 : 0.01
messages_id_rand() ->
R = random:uniform(),
if R =< 0.1 ->
true ->
Messages = lists:map(fun(#minichat{id = Id}) -> Id end, euphorik_bd:messages(8)),
if
- R > 0.1 andalso R =< 0.8 ->
+ R > 0.1 andalso R =< 0.95 ->
tire_element_rand(1, Messages);
- R > 0.8 andalso R =< 0.95 ->
+ R > 0.95 andalso R =< 0.99 ->
tire_element_rand(2, Messages);
true ->
tire_element_rand(3, Messages)
% attend un temp aléatoire compris entre INTERVALLE_MIN sec et INTERVALLE_MAX sec
timer:sleep(1000 * (random:uniform(?INTERVALLE_MAX - ?INTERVALLE_MIN + 1) + ?INTERVALLE_MIN - 1)),
% poste un message aléatoire par une personne aléatoire répondant à des messages aléatoires
- {Message, Repond_a} = {message_rand(), messages_id_rand()},\r
- %{Message, Repond_a} = {"blablablablablabla", []},
- io:format("~p poste ~p et repond a ~w~n", [User_id, Message, Repond_a]),
+ {Message, Repond_a} = {message_rand(), messages_id_rand()},
+ % io:format("~p poste ~p et repond a ~w~n", [User_id, Message, Repond_a]),
case euphorik_bd:nouveau_message(Message, User_id, Repond_a) of
{erreur, E} ->
io:format("~p : erreur : ~p~n", [User_id, E]),
loop(User_id, M - 1)
end.
+
+% Permet de tester la vitesse d'écriture en fonction de la
+% taille de la BD
+% voir : http://erlang.org/pipermail/erlang-questions/2008-October/038697.html
+bench_write_minichat(Filename) ->
+ Times = bench_write_minichat(1, []),
+ {ok, File} = file:open(Filename, [write]),
+ lists:foreach(
+ fun({Id, Time}) ->
+ io:format(File, "~w ~w~n", [Id, Time])
+ end,
+ Times
+ ),
+ file:close(File).
+bench_write_minichat(100000, Temps) -> Temps;
+bench_write_minichat(N, Temps) ->
+ {T, _} = timer:tc(mnesia, transaction, [fun() ->
+ Id = mnesia:dirty_update_counter(counter, minichat, 1),
+ mnesia:write(#minichat{
+ id = Id,
+ auteur_id = random:uniform(10000),
+ date = now(),
+ pseudo = "Test",
+ contenu = "Blabla blabla bla.",
+ racine_id = random:uniform(10000)
+ })
+ end]),
+ bench_write_minichat(N + 1, if N rem 500 =:= 0 -> [{N, T} | Temps]; true -> Temps end).
+
+
+
\ No newline at end of file
+% coding: utf-8
% Copyright 2008 Grégory Burri
%
% This file is part of Euphorik.
}).\r
\r
+
+
-record(user,
{
id,
-#!/bin/bash\r
+#!/bin/bash
# screen est utilisé par exemple pour lancé une version de preproduction et permettre de la faire tourner après un délog
-screen -S yawspreprod yaws --conf ./yaws.conf --sname yaws_dev --mnesiadir "../var/BD/" -I debian_yaws_dev
+#screen -S yawspreprod
+yaws --conf ./yaws.conf --sname yaws_dev --mnesiadir "../BD/" -I debian_yaws_dev