/* Hey Emacs, this is -*- LPC -*- ! */
/*
* $Id: error_tracker_master.c,v 1.7 2000/02/24 15:39:37 turrican Exp $
*
* By Sin
*/
#include <board.h>
inherit "/global/player/path";
inherit ERRORS_BASE;
string domain = "unset";
string tracker_name = "generic error tracker";
string error_file = "/ERROR_REPORTS";
string *other_dirs = ({ });
int period = 604800;
int nexttime;
nosave string *queue;
nosave string *messages;
nosave object tester;
nosave string save_file;
nosave int error_total;
nosave int typo_total;
nosave int idea_total;
nosave int key;
#define ERROR_INDEX 0
#define TYPO_INDEX 1
#define IDEA_INDEX 2
/* Define this to use the old ERROR_REPORTS file system */
#undef OLD_SYTEM
void do_the_work();
protected void save_me()
{
if (domain != "unset")
unguarded( (: save_object, save_file, 0 :) );
}
void create()
{
int retval;
queue = ({ });
messages = ({ });
tester = 0;
seteuid(master()->creator_file(file_name()));
save_file = file_name();
if (catch(retval = unguarded((: restore_object, save_file, 1 :))) ||
!retval) {
string temp;
temp = "/save/" + replace(file_name()[1..], "/", "_");
if (catch(retval = unguarded((: restore_object, temp, 1 :))) ||
!retval) {
/* The save file doesn't exist. Try to make it here, then
* /save */
if (catch(save_me()))
save_file = temp;
} else
save_file = temp;
}
if (!retval) {
nexttime = 0;
}
if (nexttime < time())
do_the_work();
else
call_out("do_the_work", nexttime - time());
}
void dest_me()
{
save_me();
if (key) {
finish_errors(key);
}
destruct(this_object());
}
nomask mixed dwep()
{
if (key) {
finish_errors(key);
}
destruct(this_object());
return "Destructed With Extreme Prejudice";
}
protected int post(string message)
{
if (tester) {
tester->more_string(message);
tester = 0;
return 0;
}
return BOARD_HAND->add_message(domain,
capitalize(tracker_name),
"Error summaries for " +
capitalize(domain),
message);
}
protected int *errors(string directory)
{
int *retval = ({ 0, 0, 0 });
#ifdef OLD_SYSTEM
string *lines;
string test;
int i, j, k;
#else
string query;
mixed ret;
#endif
#ifdef OLD_SYSTEM
if (file_size(directory) != -2) return retval;
if (file_size(directory + error_file) <= 0) return retval;
lines = explode(read_file(directory + error_file), "\n");
for (i = 0, j = sizeof(lines); i < j; i++) {
if (sscanf(lines[i], ".START %d", k) == 1) {
i++;
if (i < j) {
if (strsrch(lines[i], "BUG") != -1)
retval[ERROR_INDEX]++;
else if (strsrch(lines[i], "IDEA") != -1)
retval[IDEA_INDEX]++;
else if (strsrch(lines[i], "TYPO") != -1)
retval[TYPO_INDEX]++;
}
test = sprintf(".END %d", k);
while (i < j && lines[i] != test) i++;
}
}
#else
query = sprintf("SELECT COUNT(*) FROM errors WHERE Directory = '%s' AND "
"Status = 'OPEN' AND Type = 'BUG'\n", directory);
ret = sql_query(key, query);
if (stringp(ret)) {
log_file("ERROR_TRACKER", "%s Error counting bugs for directory %s : %s\n",
ctime(time()), directory, ret);
} else if (ret) {
ret = get_row(key, 1);
if (stringp(ret)) {
log_file("ERROR_TRACKER", "%s Error counting bugs for directory %s : "
"%s\n", ctime(time()), directory, ret);
} else {
retval[ERROR_INDEX] = values(ret)[0];
}
}
query = sprintf("SELECT COUNT(*) FROM errors WHERE Directory = '%s' AND "
"Status = 'OPEN' AND Type = 'IDEA';", directory);
ret = sql_query(key, query);
if (stringp(ret)) {
log_file("ERROR_TRACKER", "%s Error counting ideas for directory %s : "
"%s\n", ctime(time()), directory, ret);
} else if (ret) {
ret = get_row(key, 1);
if (stringp(ret)) {
log_file("ERROR_TRACKER", "%s Error counting ideas for directory %s : "
"%s\n", ctime(time()), directory, ret);
} else {
retval[IDEA_INDEX] = values(ret)[0];
}
}
query = sprintf("SELECT COUNT(*) FROM errors WHERE Directory = '%s' AND "
"Status = 'OPEN' AND Type = 'TYPO';", directory);
ret = sql_query(key, query);
if (stringp(ret)) {
log_file("ERROR_TRACKER", "%s Error counting typos for directory %s : "
"%s\n", ctime(time()), directory, ret);
} else if (ret) {
ret = get_row(key, 1);
if (stringp(ret)) {
log_file("ERROR_TRACKER", "%s Error counting typos for directory %s : "
"%s\n", ctime(time()), directory, ret);
} else {
retval[TYPO_INDEX] = values(ret)[0];
}
}
#endif
return retval;
}
protected string dodir(string directory)
{
string mesg;
string file;
string *files;
string *dirs;
int *counts;
counts = errors(directory);
if (counts[0] || counts[1] || counts[2]) {
mesg = sprintf("%4d %4d %4d %s", counts[ERROR_INDEX],
counts[TYPO_INDEX], counts[IDEA_INDEX], directory);
error_total += counts[ERROR_INDEX];
typo_total += counts[TYPO_INDEX];
idea_total += counts[IDEA_INDEX];
} else
mesg = 0;
files = get_files(directory + "/*");
dirs = ({ });
foreach (file in files) {
if (file[<2..] == "/." || file[<3..] == "/..")
continue;
if (file_size(file) == -2)
dirs += ({ file });
}
queue = dirs + queue;
return mesg;
}
protected void iterate()
{
if (sizeof(queue)) {
string dir = queue[0];
if (sizeof(queue) > 1)
queue = queue[1..];
else
queue = ({ });
messages += ({ dodir(dir) });
call_out((: iterate() :), 1);
} else {
string message;
message = implode(messages - ({ 0 }), "\n");
if (sizeof(message) == 0) {
message = "Congratulations! There are no errors in all of " +
capitalize(domain) + "!\n";
} else {
message = "There are reports in the following directories in " +
capitalize(domain) + "\n" +
" BUG TYPO IDEA\n" +
message +
sprintf("\n%4d %4d %4d TOTAL\n",
error_total, typo_total, idea_total);
}
post(message);
messages = ({ });
#ifndef OLD_SYSTEM
finish_errors(key);
key = 0;
#endif
}
}
void do_the_work()
{
string ret;
if (domain == "unset") return;
nexttime = time() + period;
call_out("do_the_work", period);
save_me();
queue = ({ "/d/" + domain }) + other_dirs;
messages = ({ });
error_total = 0;
idea_total = 0;
typo_total = 0;
#ifndef OLD_SYSTEM
key = time();
ret = init_errors(key, "atuin");
if (ret) {
log_file("ERROR_TRACKER", "%s Error initializing errors database for "
"domain %s : %s\n", ctime(key), domain, ret);
return;
}
#endif
iterate();
}
varargs void test(string dir)
{
mixed ret;
tester = this_player();
if (dir && stringp(dir) && dir != "")
queue = ({ dir });
else
queue = ({ "/d/klatch/djel" });
messages = ({ });
#ifndef OLD_SYSTEM
key = time();
ret = init_errors(key, "atuin");
if (ret) {
printf("Error initializing errors database for directory %s : %s\n", dir, ret);
return;
}
#endif
iterate();
}
void set_name(string name)
{
tracker_name = name;
save_me();
}
void set_domain(string name)
{
domain = name;
save_me();
}
void set_period(int length)
{
remove_call_out("do_the_work");
nexttime -= period;
period = length;
nexttime += period;
save_me();
if (nexttime < time())
do_the_work();
else
call_out("do_the_work", nexttime - time());
}
void set_error_file(string name)
{
error_file = name;
save_me();
}
void set_other_dirs(string *others)
{
if (arrayp(others))
other_dirs = others;
else
other_dirs = ({ });
save_me();
}
mixed stats()
{
return ({
({ "domain", domain }),
({ "name", tracker_name }),
({ "error file", error_file }),
({ "period", period }),
({ "next time", ctime(nexttime) }),
({ "testing by", tester }),
({ "queue length", sizeof(queue) }),
({ "message length", sizeof(messages - ({ 0 })) }),
({ "other dirs", sizeof(other_dirs) ? implode(other_dirs, ", ") : 0 }),
({ "save file", save_file }),
});
}