// // WordMonitor.cc // // Part of the ht://Dig package // Copyright (c) 1999-2004 The ht://Dig Group // For copyright details, see the file COPYING in your distribution // or the GNU Library General Public License (LGPL) version 2 or later // // // $Id: WordMonitor.cc,v 1.7 2004/05/28 13:15:28 lha Exp $ // #ifdef HAVE_CONFIG_H #include "htconfig.h" #endif /* HAVE_CONFIG_H */ #include #include #ifndef _MSC_VER /* _WIN32 */ #include #endif #include "StringList.h" #include "WordMonitor.h" #define WORD_MONITOR_RRD 1 #define WORD_MONITOR_READABLE 2 WordMonitor* WordMonitor::instance = 0; char* WordMonitor::values_names[WORD_MONITOR_VALUES_SIZE] = { "", "C.Write", "C.Read", "C.Compress 1/1", "C.Compress 1/2", "C.Compress 1/3", "C.Compress 1/4", "C.Compress 1/5", "C.Compress 1/6", "C.Compress 1/7", "C.Compress 1/8", "C.Compress 1/9", "C.Compress 1/10", "C.Compress 1/>10", "C.P_IBTREE", "C.P_LBTREE", "C.P_UNKNOWN", "C.Put", "C.Get (0)", "C.Get (NEXT)", "C.Get (SET_RANGE)", "C.Get (Other)", "G.LEVEL", "G.PGNO", "C.CMP", 0 }; WordMonitor::WordMonitor(const Configuration &config) { memset((char*)values, '\0', sizeof(unsigned int) * WORD_MONITOR_VALUES_SIZE); memset((char*)old_values, '\0', sizeof(unsigned int) * WORD_MONITOR_VALUES_SIZE); started = elapsed = time(0); output_style = WORD_MONITOR_READABLE; if((period = config.Value("wordlist_monitor_period"))) { const String& desc = config.Find("wordlist_monitor_output"); StringList fields(desc, ','); if(fields.Count() > 0) { char* filename = fields[0]; if(filename[0] == '\0') output = stderr; else { output = fopen(filename, "a"); if(!output) { fprintf(stderr, "WordMonitor::WordMonitor: cannot open %s for writing ", filename); perror(""); output = stderr; return; } } if(fields.Count() > 1) { char* style = fields[1]; if(!mystrcasecmp(style, "rrd")) output_style = WORD_MONITOR_RRD; else output_style = WORD_MONITOR_READABLE; } } TimerStart(); } } WordMonitor::~WordMonitor() { TimerStop(); if(output != stderr) fclose(output); } void WordMonitor::Initialize(const Configuration &config_arg) { if(instance != 0) delete instance; instance = new WordMonitor(config_arg); } const String WordMonitor::Report() const { String output; int i; time_t now = time(0); if(output_style == WORD_MONITOR_RRD) output << (int)now << ":"; for(i = 0; i < WORD_MONITOR_VALUES_SIZE; i++) { if(!values_names[i]) break; if(values_names[i][0]) { if(output_style == WORD_MONITOR_READABLE) { output << values_names[i] << ": " << values[i]; if((now - elapsed) > 0) { output << ", per sec : " << (int)(values[i] / (now - started)); output << ", delta : " << (values[i] - old_values[i]); output << ", per sec : " << (int)((values[i] - old_values[i]) / (now - elapsed)); } output << "|"; } else if(output_style == WORD_MONITOR_RRD) { output << values[i] << ":"; } } } memcpy((char*)old_values, (char*)values, sizeof(unsigned int) * WORD_MONITOR_VALUES_SIZE); return output; } static void handler_alarm(int signal) { WordMonitor* monitor = WordMonitor::Instance(); if(!monitor) { fprintf(stderr, "WordMonitor::handler_alarm: no instance\n"); return; } monitor->TimerClick(signal); } void WordMonitor::TimerStart() { if(period < 5) { fprintf(stderr, "WordMonitor::TimerStart: wordlist_monitor_period must be > 5 (currently %d) otherwise monitoring is not accurate\n", period); return; } #ifndef _MSC_VER /* _WIN32 */ struct sigaction action; struct sigaction old_action; memset((char*)&action, '\0', sizeof(struct sigaction)); memset((char*)&old_action, '\0', sizeof(struct sigaction)); action.sa_handler = handler_alarm; if(sigaction(SIGALRM, &action, &old_action) != 0) { fprintf(stderr, "WordMonitor::TimerStart: installing SIGALRM "); perror(""); } if(old_action.sa_handler != SIG_DFL) { fprintf(stderr, "WordMonitor::TimerStart: found an installed action while installing SIGALRM, restoring old action\n"); if(sigaction(SIGALRM, &old_action, NULL) != 0) { fprintf(stderr, "WordMonitor::TimerStart: installing old SIGALRM "); perror(""); } return; } #endif fprintf(output, "----------------- WordMonitor starting -------------------\n"); if(output_style == WORD_MONITOR_RRD) { fprintf(output, "Started:%ld\n", started); fprintf(output, "Period:%d\n", period); fprintf(output, "Time:"); int i; for(i = 0; i < WORD_MONITOR_VALUES_SIZE; i++) { if(!values_names[i]) break; if(values_names[i][0]) fprintf(output, "%s:", values_names[i]); } fprintf(output, "\n"); } fflush(output); TimerClick(0); } void WordMonitor::TimerClick(int signal) { if(signal) { // // Do not report if less than since last report. // if(time(0) - elapsed >= period) { fprintf(output, "%s\n", (const char*)Report()); elapsed = time(0); fflush(output); } } #ifndef _MSC_VER /* _WIN32 */ alarm(period); #endif } void WordMonitor::TimerStop() { if(period > 0) { #ifndef _MSC_VER /* _WIN32 */ alarm(0); struct sigaction action; memset((char*)&action, '\0', sizeof(struct sigaction)); action.sa_handler = SIG_DFL; if(sigaction(SIGALRM, &action, NULL) != 0) { fprintf(stderr, "WordMonitor::TimerStart: resetting SIGALRM to SIG_DFL "); perror(""); } // Make sure last report is at least one second older than the previous one. // if(time(0) - elapsed < 1) sleep(2); fprintf(output, "%s\n", (const char*)Report()); fprintf(output, "----------------- WordMonitor finished -------------------\n"); #endif } } // // C interface to WordMonitor instance // extern "C" { void word_monitor_click() { WordMonitor* monitor = WordMonitor::Instance(); #ifndef _MSC_VER /* _WIN32 */ if(monitor) monitor->TimerClick(SIGALRM); #endif } void word_monitor_add(int index, unsigned int value) { WordMonitor* monitor = WordMonitor::Instance(); if(monitor) monitor->Add(index, value); } void word_monitor_set(int index, unsigned int value) { WordMonitor* monitor = WordMonitor::Instance(); if(monitor) monitor->Set(index, value); } unsigned int word_monitor_get(int index) { WordMonitor* monitor = WordMonitor::Instance(); if(monitor) return monitor->Get(index); else return 0; } }