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

310 lines
7.0 KiB
C

/*
* binkleyforce -- unix FTN mailer project
*
* Copyright (c) 1998-2000 Alexander Belkin, 2:5020/1398.11
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* $Id$
*/
#include "includes.h"
#include "confread.h"
#include "logger.h"
#include "bforce.h"
#include "util.h"
#include "nodelist.h"
#include "session.h"
/*
* Format of 'sts' files (project only..)
*
* Header:
* 0 byte - version (current is 1)
* 1 byte - global undialable flag (for all lines)
* 2 word - tries
* 4 word - handshake tries
* 6 dword - hold all calls until
* 8 dword - node will not accept our file requests till this time
* 10 dword - last successfull outgoing session
* 12 dword - last successfull incoming session
*
* Each entry (per-line statistics)
*/
void session_stat_reset_counters(s_sess_stat *stat)
{
stat->tries = TRIES_RESET;
stat->tries_noansw = TRIES_RESET;
stat->tries_noconn = TRIES_RESET;
stat->tries_nodial = TRIES_RESET;
stat->tries_hshake = TRIES_RESET;
stat->tries_sessns = TRIES_RESET;
}
static char *session_stat_get_stsfile(s_faddr *addr, int linenum)
{
char buf[32];
char *yield = NULL;
char *p_stsdir = conf_string(cf_status_directory);
if( p_stsdir && *p_stsdir )
{
if( linenum == -1 )
sprintf(buf, "%u.%u.%u.%u.sts",
addr->zone, addr->net,
addr->node, addr->point);
else
sprintf(buf, "%u.%u.%u.%u-%u.sts",
addr->zone, addr->net,
addr->node, addr->point, linenum);
yield = string_concat(p_stsdir, buf, NULL);
}
return yield;
}
static int session_stat_read_stsfile(FILE *fp, s_sess_stat *stat)
{
int res;
if( fseek(fp, 0, SEEK_SET) == -1 )
return -1;
memset(stat, '\0', sizeof(s_sess_stat));
res = fscanf(fp, "%u %u %u %u %u %u %lu %lu %lu %lu",
(unsigned int *) &stat->tries,
(unsigned int *) &stat->tries_noconn,
(unsigned int *) &stat->tries_noansw,
(unsigned int *) &stat->tries_nodial,
(unsigned int *) &stat->tries_hshake,
(unsigned int *) &stat->tries_sessns,
(unsigned long *) &stat->hold_until,
(unsigned long *) &stat->hold_freqs,
(unsigned long *) &stat->last_success_out,
(unsigned long *) &stat->last_success_in);
if (res == 0) {
log("Read STS unsuccessfull...");
return -1;
}
/* Set last successfull session time */
stat->last_success = MAX(stat->last_success_out, stat->last_success_in);
return 0;
}
static int session_stat_write_stsfile(FILE *fp, s_sess_stat *stat)
{
if( fseek(fp, 0, SEEK_SET) == -1 )
return -1;
fprintf(fp, "%u %u %u %u %u %u %lu %lu %lu %lu",
(unsigned int) stat->tries,
(unsigned int) stat->tries_noconn,
(unsigned int) stat->tries_noansw,
(unsigned int) stat->tries_nodial,
(unsigned int) stat->tries_hshake,
(unsigned int) stat->tries_sessns,
(unsigned long) stat->hold_until,
(unsigned long) stat->hold_freqs,
(unsigned long) stat->last_success_out,
(unsigned long) stat->last_success_in);
return 0;
}
static int session_stat_update_stsfile(const char *stsname, s_sess_stat *stat)
{
int rc = 0;
FILE *sts_fp = NULL;
s_sess_stat tmpstat;
bool stsexist = FALSE;
memset(&tmpstat, '\0', sizeof(s_sess_stat));
stsexist = (access(stsname, R_OK) == 0);
if( (sts_fp = file_open(stsname, stsexist ? "r+" : "w")) == NULL )
{
logerr("cannot open status file \"%s\"", stsname);
gotoexit(-1);
}
if( stsexist )
{
/* Ignore read errors */
(void)session_stat_read_stsfile(sts_fp, &tmpstat);
if( ftruncate(fileno(sts_fp), 0) == -1 )
{
logerr("cannot truncate status file \"%s\"", stsname);
gotoexit(-1);
}
}
/*
* Update statistic
*/
if( stat->tries == TRIES_RESET )
tmpstat.tries = 0;
else
tmpstat.tries += stat->tries;
if( stat->tries_noconn == TRIES_RESET )
tmpstat.tries_noconn = 0;
else
tmpstat.tries_noconn += stat->tries_noconn;
if( stat->tries_nodial == TRIES_RESET )
tmpstat.tries_nodial = 0;
else
tmpstat.tries_nodial += stat->tries_nodial;
if( stat->tries_noansw == TRIES_RESET )
tmpstat.tries_noansw = 0;
else
tmpstat.tries_noansw += stat->tries_noansw;
if( stat->tries_hshake == TRIES_RESET )
tmpstat.tries_hshake = 0;
else
tmpstat.tries_hshake += stat->tries_hshake;
if( stat->tries_sessns == TRIES_RESET )
tmpstat.tries_sessns = 0;
else
tmpstat.tries_sessns += stat->tries_sessns;
if( stat->hold_until == HOLD_RESET )
tmpstat.hold_until = 0;
else if( stat->hold_until > tmpstat.hold_until )
tmpstat.hold_until = stat->hold_until;
if( stat->hold_freqs == HOLD_RESET )
tmpstat.hold_freqs = 0;
else if( stat->hold_freqs > tmpstat.hold_freqs )
tmpstat.hold_freqs = stat->hold_freqs;
if( stat->last_success_out > tmpstat.last_success_out )
tmpstat.last_success_out = stat->last_success_out;
if( stat->last_success_in > tmpstat.last_success_in )
tmpstat.last_success_in = stat->last_success_in;
/*
* Write new statistic to the 'sts' file
*/
if( session_stat_write_stsfile(sts_fp, &tmpstat) == -1 )
{
logerr("error writing status file \"%s\"", stsname);
gotoexit(-1);
}
exit:
if( sts_fp )
file_close(sts_fp);
return rc;
}
int session_stat_get(s_sess_stat *stat, s_faddr *addr)
{
FILE *fp;
char *stsname = session_stat_get_stsfile(addr, -1);
memset(stat, '\0', sizeof(s_sess_stat));
if( stsname )
{
fp = file_open(stsname, "r");
if( !fp )
{
free(stsname);
return -1;
}
(void)session_stat_read_stsfile(fp, stat);
(void)file_close(fp);
free(stsname);
}
return 0;
}
int session_stat_apply_diff(s_faddr addr, s_sess_stat stat)
{
int rc;
char *stsname = session_stat_get_stsfile(&addr, -1);
if( !stsname )
return -1;
rc = session_stat_update_stsfile(stsname, &stat);
free(stsname);
return rc;
}
int session_stat_update(s_faddr *addr, s_sess_stat *stat, bool caller, int rc)
{
char *stsname;
/*
* Update sessions statistic depending on session
* return code. The latter must be one of BFERR
* values. Warning, stat structure might allready
* contain desired settings!
*/
if( rc == BFERR_NOERROR )
{
if( caller )
stat->last_success_out = time(NULL);
else
stat->last_success_in = time(NULL);
session_stat_reset_counters(stat);
}
else
{
if( caller )
{
stat->tries++;
if( rc == BFERR_HANDSHAKE_ERROR )
stat->tries_hshake++;
if( rc == BFERR_CANT_CONNECT14 )
stat->tries_noansw++;
if( rc == BFERR_CANT_CONNECT13 )
stat->tries_nodial++;
if( BFERR_CANT_CONNECT10 <= rc && rc <= BFERR_CANT_CONNECT19 )
stat->tries_noconn++;
if( rc >= BFERR_CONNECT_TOOLOW )
stat->tries_sessns++;
/* Reset some counters */
if( rc >= BFERR_CONNECT_TOOLOW )
{
stat->tries_noansw = TRIES_RESET;
stat->tries_noconn = TRIES_RESET;
}
if( rc > BFERR_HANDSHAKE_ERROR )
stat->tries_hshake = TRIES_RESET;
}
}
stsname = session_stat_get_stsfile(addr, -1);
if( !stsname )
return -1;
rc = session_stat_update_stsfile(stsname, stat);
free(stsname);
return rc;
}