blob: c02873e07d67217b4627531b027ab8e1caa24c7d [file] [log] [blame]
MG Mud User88f12472016-06-24 23:31:02 +02001// MorgenGrauen MUDlib
2/** \file /p/daemon/sastatd.c
3* Statistikdaemon fuer Skill-Attribute
4* Der Daemon loggt SA-Modifier und schreibt sie von Zeit zu Zeit auf die
5* Platte.
6* \author Zesstra
7* \date 06.08.2008
8* \version $Id$
9*/
10/* Changelog:
11*/
12#pragma strong_types,save_types
13#pragma no_clone,no_inherit,no_shadow
14#pragma pedantic,range_check
15
16#include <defines.h>
17
18/** anfaengliche Groesse des Log-Puffers
19 */
20#define DEFAULT_BUFFER_LEN 200
21/** ab dieser Anzahl an Eintraegen wird im naechsten Backend-Zyklus vom Driver
22 * per Callout der Puffer weggeschrieben. */
23#define BUFFERTHRESHOLD 150
24
25/** Logfile fuer die Stats
26 */
27#define STATLOG "SASTATS"
28/** max. Logfilegroesse (3 MB)
29 */
30#define MAXLOGSIZE 3145728
31
32struct log_entry_s {
33 int timestamp;
34 string liv;
35 string caster;
36 string atrname;
37 mixed value;
38 int duration;
39};
40
41struct log_buffer_s {
42 mixed buf; // Array von log_entry
43 int bufferlen; // Laenge des Buffers, kann dyn. vergroessert werden.
44 int sp; // oberster Eintrag im Buffer (letztendlich nen Stack).
45};
46
47/** speichert Logeintraege mit indiv. Modifiereintraegen.
48 * Array von log_entry_s mit Info ueber Pufferlaenge und zuletzt
49 * geschriebenem Arrayeintrag.
50*/
51struct log_buffer_s logbuf = (<log_buffer_s>
52 buf : allocate(DEFAULT_BUFFER_LEN),
53 bufferlen : DEFAULT_BUFFER_LEN,
54 // -1, weil der sp beim Loggen zuerst erhoeht wird und sonst Elemente 0
55 // leer bleibt.
56 sp : -1 );
57
58/** \def DEBUG
59 Outputs debug message to Maintainer, if Mainteiner is logged in.
60*/
61#ifndef DEBUG
62#define DEBUG(x) if (find_player("zesstra"))\
63 tell_object(find_player("zesstra"),\
64 "EDBG: "+x+"\n")
65#endif
66
67private string FormatLogEntry(struct log_entry_s entry) {
68 return sprintf("[%s] %s, %s, %s, %s, %d\n",
69 strftime("%d%m%y-%H%M%S",entry->timestamp),
70 entry->liv, entry->caster, entry->atrname,
71 entry->value, entry->duration);
72}
73
74private void WriteBuffer() {
75 // relevanten Teil des Puffers extrahieren.
76 mixed buf = logbuf->buf[0..logbuf->sp];
77 // dann alle Eintraege in Strings mappen
78 buf = map(buf, #'FormatLogEntry);
79 // wegschreiben
80 log_file(STATLOG, sprintf("%@s",buf), MAXLOGSIZE);
81 // sp auf den Pufferanfang setzen
82 logbuf->sp = -1;
83}
84
85public void LogModifier(object caster, string atrname,
86 mixed value, int duration) {
87 // nur Spieler sind interessant
88 if (!query_once_interactive(previous_object()))
89 return;
90
91 // sp um eins erhoehen und schauen, ob die Puffergroesse ueberschritten
92 // wurde. Wenn ja, Puffer vergroessern.
93 logbuf->sp++;
94 if (logbuf->sp >= logbuf->bufferlen) {
95 logbuf->buf = logbuf->buf + allocate(50);
96 logbuf->bufferlen += 50;
97 }
98 // eintragen. Interessanterweise ist es tatsaechlich kein Problem, wenn
99 // Structmember und lokale Variablen hier den gleichen Namen habem. ;-)
100 logbuf->buf[logbuf->sp] = (<log_entry_s>
101 timestamp : time(),
102 liv : getuid(previous_object()), // nur Spieler
103 caster : object_name(caster),
104 atrname : atrname,
105 value : to_string(value), // wegen (fluechtiger) Closures
106 duration : duration );
107 // wegschreiben veranlassen
108 if (logbuf->sp > BUFFERTHRESHOLD
109 && find_call_out(#'WriteBuffer) == -1)
110 call_out(#'WriteBuffer, 0);
111}
112
113protected void create() {
114 seteuid(getuid(ME));
115}
116
117varargs public int remove(int silent) {
118 if (logbuf->sp > -1)
119 WriteBuffer();
120 destruct(ME);
121 return 1;
122}
123
124void reset() {
125 // ggf. Puffer wegschreiben.
126 if (logbuf->sp > BUFFERTHRESHOLD)
127 WriteBuffer();
128 // ggf. sehr grosse Puffer verkleinern
129 if (logbuf->bufferlen > DEFAULT_BUFFER_LEN * 2) {
130 logbuf->buf = allocate(DEFAULT_BUFFER_LEN);
131 logbuf->bufferlen = DEFAULT_BUFFER_LEN;
132 logbuf->sp = -1;
133 }
134}
135