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
273 lines
6.5 KiB
3 years ago
|
//
|
||
|
// 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;
|
||
|
}
|
||
|
}
|