/* 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 }), }); }