You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

273 lines
6.5 KiB

//
// WordMonitor.cc
//
// Part of the ht://Dig package <http://www.htdig.org/>
// 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
// <http://www.gnu.org/copyleft/lgpl.html>
//
// $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 <stdlib.h>
#include <signal.h>
#ifndef _MSC_VER /* _WIN32 */
#include <unistd.h>
#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 <period> 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;
}
}