614 lines
12 KiB
C++
614 lines
12 KiB
C++
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <vector>
|
|
|
|
#include "StatClient.h"
|
|
#include "StatAttn.h"
|
|
#include "formater.h"
|
|
#include "DtcStatAlarmReporter.h"
|
|
#include "stat_index.h"
|
|
//#include "daemon.h"
|
|
//#include "ttc_global.h"
|
|
|
|
const char progname[] = "stattool";
|
|
const char usage_argv[] = "dump Id or reporter";
|
|
char cacheFile[256] = "index.conf";
|
|
char tableFile[256] = "";
|
|
CStatClient stc;
|
|
std::vector<CStatClient::iterator> idset;
|
|
CTableFormater out;
|
|
int outfmt = CTableFormater::FORMAT_ALIGNED;
|
|
unsigned char outnoname;
|
|
unsigned char rawdata;
|
|
unsigned char alldata;
|
|
unsigned char nobase;
|
|
|
|
|
|
#if __WORDSIZE >= 64
|
|
#define F64 "%ld"
|
|
#else
|
|
#define F64 "%lld"
|
|
#endif
|
|
|
|
static inline void cell_id(unsigned int id)
|
|
{
|
|
out.Cell("%u", id);
|
|
}
|
|
|
|
static inline void cell_sample_id(unsigned int id, unsigned int n)
|
|
{
|
|
if(outnoname)
|
|
out.Cell("%u.%u", id, n);
|
|
else
|
|
out.Cell("%u", id);
|
|
}
|
|
|
|
static inline void cell_name(const char *name)
|
|
{
|
|
if(outnoname) return;
|
|
if(outfmt == CTableFormater::FORMAT_ALIGNED)
|
|
out.Cell("%s:", name);
|
|
else
|
|
out.Cell("%s", name);
|
|
}
|
|
|
|
static inline void cell_dummy(void)
|
|
{
|
|
if(outfmt == CTableFormater::FORMAT_ALIGNED)
|
|
out.Cell("-");
|
|
else
|
|
#if GCC_MAJOR < 3
|
|
out.Cell(" ");
|
|
#else
|
|
out.Cell(NULL);
|
|
#endif
|
|
}
|
|
|
|
static inline void cell_base(int64_t v)
|
|
{
|
|
if(outnoname) return;
|
|
if(outfmt == CTableFormater::FORMAT_ALIGNED)
|
|
out.Cell("count[>="F64"]:", v);
|
|
else
|
|
out.Cell("count[>="F64"]", v);
|
|
}
|
|
|
|
static inline void cell_nbase(int v)
|
|
{
|
|
if(outfmt == CTableFormater::FORMAT_ALIGNED)
|
|
out.Cell("[%d]", v);
|
|
else
|
|
out.Cell("%d", v);
|
|
}
|
|
|
|
static inline void cell_int(int64_t val)
|
|
{
|
|
out.Cell(F64, val);
|
|
}
|
|
|
|
static inline void cell_fixed(int64_t val, int n, int div)
|
|
{
|
|
const char *sign = "";
|
|
if(val < 0)
|
|
{
|
|
val = - val;
|
|
sign = "-";
|
|
}
|
|
|
|
out.Cell("%s"F64".%0*d", sign, val/div, n, (int)(val%div));
|
|
}
|
|
|
|
static inline void cell_percent(int64_t val)
|
|
{
|
|
out.Cell(F64"%%", val);
|
|
}
|
|
|
|
static inline void cell_percent_fixed(int64_t val, int n, int div)
|
|
{
|
|
const char *sign = "";
|
|
if(val < 0)
|
|
{
|
|
val = - val;
|
|
sign = "-";
|
|
}
|
|
|
|
out.Cell("%s"F64".%0*d%%", sign, val/div, n, (int)(val%div));
|
|
}
|
|
|
|
static inline void cell_hms(int64_t val)
|
|
{
|
|
const char *sign = "";
|
|
if(val < 0)
|
|
{
|
|
val = - val;
|
|
sign = "-";
|
|
}
|
|
|
|
if(val < 60)
|
|
out.Cell("%s%d", sign, (int)val);
|
|
else if(val < 60*60)
|
|
out.Cell("%s%d:%02d", sign, (int)(val/60), (int)(val%60));
|
|
else
|
|
out.Cell("%s"F64":%02d:%02d", sign, val/3600, (int)((val/60)%60), (int)(val%60));
|
|
}
|
|
|
|
static inline void cell_hmsmsec(int64_t val)
|
|
{
|
|
const char *sign = "";
|
|
if(val < 0)
|
|
{
|
|
val = - val;
|
|
sign = "-";
|
|
}
|
|
if(val < 60*1000)
|
|
out.Cell("%s%d.%03d", sign, (int)(val/1000), (int)(val%1000));
|
|
else if(val < 60*60*1000)
|
|
out.Cell("%s%d:%02d.%03d", sign, (int)(val/60000), (int)((val/1000)%60), (int)(val%1000));
|
|
else
|
|
out.Cell("%s"F64":%02d:%02d.%03d", sign,
|
|
val/3600000, (int)((val/60000)%60), (int)((val/1000)%60), (int)(val%1000));
|
|
}
|
|
|
|
static inline void cell_hmsusec(int64_t val)
|
|
{
|
|
const char *sign = "";
|
|
if(val < 0)
|
|
{
|
|
val = - val;
|
|
sign = "-";
|
|
}
|
|
out.Cell("%s"F64".%06d", sign, val/1000000, (int)(val%1000000));
|
|
}
|
|
|
|
static inline void cell_datetime(int64_t v)
|
|
{
|
|
if(v==0) {
|
|
out.CellV("-");
|
|
return;
|
|
}
|
|
time_t t = v;
|
|
struct tm tm;
|
|
localtime_r(&t, &tm);
|
|
out.CellV("%d-%d-%d %d:%02d:%02d",
|
|
tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday,
|
|
tm.tm_hour, tm.tm_min, tm.tm_sec);
|
|
}
|
|
|
|
static inline void cell_date(int64_t v)
|
|
{
|
|
if(v==0) {
|
|
out.CellV("-");
|
|
return;
|
|
}
|
|
time_t t = v;
|
|
struct tm tm;
|
|
localtime_r(&t, &tm);
|
|
out.CellV("%d-%d-%d",
|
|
tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday);
|
|
}
|
|
|
|
static inline void cell_version(int64_t v)
|
|
{
|
|
out.CellV("%d.%d.%d", (int)v/10000, (int)v/100%100, (int)v%100);
|
|
}
|
|
|
|
static inline void cell_bool(int64_t v)
|
|
{
|
|
if(0 == v)
|
|
{
|
|
out.CellV("NO");
|
|
}
|
|
else
|
|
{
|
|
out.CellV("YES");
|
|
}
|
|
}
|
|
|
|
|
|
inline void row_init(void)
|
|
{
|
|
out.NewRow();
|
|
}
|
|
|
|
inline void row_clear(void)
|
|
{
|
|
out.ClearRow();
|
|
}
|
|
|
|
inline void dump_table(void)
|
|
{
|
|
out.Dump(stdout, outfmt);
|
|
}
|
|
|
|
void cell_value(int unit, int64_t val)
|
|
{
|
|
if(rawdata) unit = SU_INT;
|
|
switch(unit)
|
|
{
|
|
default:
|
|
case SU_HIDE:
|
|
case SU_INT: cell_int(val); break;
|
|
case SU_INT_1: cell_fixed(val, 1, 10); break;
|
|
case SU_INT_2: cell_fixed(val, 2, 100); break;
|
|
case SU_INT_3: cell_fixed(val, 3, 1000); break;
|
|
case SU_INT_4: cell_fixed(val, 4, 10000); break;
|
|
case SU_INT_5: cell_fixed(val, 5, 100000); break;
|
|
case SU_INT_6: cell_fixed(val, 6, 1000000); break;
|
|
case SU_MSEC: cell_hmsmsec(val); break;
|
|
case SU_USEC: cell_hmsusec(val); break;
|
|
case SU_TIME: cell_hms(val); break;
|
|
case SU_DATE: cell_date(val); break;
|
|
case SU_DATETIME: cell_datetime(val); break;
|
|
case SU_VERSION: cell_version(val); break;
|
|
case SU_BOOL: cell_bool(val); break;
|
|
case SU_PERCENT: cell_percent(val); break;
|
|
case SU_PERCENT_1: cell_percent_fixed(val, 1, 10); break;
|
|
case SU_PERCENT_2: cell_percent_fixed(val, 2, 100); break;
|
|
case SU_PERCENT_3: cell_percent_fixed(val, 3, 1000); break;
|
|
}
|
|
}
|
|
|
|
void dump_data(void)
|
|
{
|
|
int64_t sc[16];
|
|
int sn;
|
|
|
|
unsigned int i;
|
|
CStatClient::iterator s;
|
|
|
|
stc.CheckPoint();
|
|
//printf("dump data %d\n",idset.size());
|
|
for(i = 0; i < idset.size(); i++)
|
|
{
|
|
s = idset[i];
|
|
|
|
if(alldata==0 && s->unit() == SU_HIDE)
|
|
continue;
|
|
|
|
row_init();
|
|
switch(s->type())
|
|
{
|
|
case SA_SAMPLE:
|
|
cell_id(s->id());
|
|
cell_name(s->name());
|
|
//cell_value(s->unit(), stc.ReadSampleAverage(s, SC_CUR));
|
|
cell_value(s->unit(), stc.ReadSampleAverage(s, SCC_10S));
|
|
cell_value(s->unit(), stc.ReadSampleAverage(s, SCC_10M));
|
|
cell_value(s->unit(), stc.ReadSampleAverage(s, SCC_ALL));
|
|
|
|
if(nobase<2)
|
|
{
|
|
row_init();
|
|
cell_sample_id(s->id(), 1);
|
|
cell_name("count[all]");
|
|
//cell_value(SU_INT, stc.ReadSampleCounter(s, SC_CUR));
|
|
cell_value(SU_INT, stc.ReadSampleCounter(s, SCC_10S));
|
|
cell_value(SU_INT, stc.ReadSampleCounter(s, SCC_10M));
|
|
cell_value(SU_INT, stc.ReadSampleCounter(s, SCC_ALL));
|
|
}
|
|
if(nobase==0)
|
|
{
|
|
sn = stc.GetCountBase(s->id(), sc);
|
|
for(int n=1; n<=sn; n++)
|
|
{
|
|
row_init();
|
|
cell_sample_id(s->id(), n+1);
|
|
cell_base(sc[n-1]);
|
|
//cell_value(SU_INT, stc.ReadSampleCounter(s, SC_CUR, n));
|
|
cell_value(SU_INT, stc.ReadSampleCounter(s, SCC_10S, n));
|
|
cell_value(SU_INT, stc.ReadSampleCounter(s, SCC_10M, n));
|
|
cell_value(SU_INT, stc.ReadSampleCounter(s, SCC_ALL, n));
|
|
}
|
|
}
|
|
|
|
break;
|
|
|
|
case SA_COUNT:
|
|
cell_id(s->id());
|
|
cell_name(s->name());
|
|
//cell_value(s->unit(), stc.ReadCounterValue(s, SC_CUR));
|
|
cell_value(s->unit(), stc.ReadCounterValue(s, SCC_10S));
|
|
cell_value(s->unit(), stc.ReadCounterValue(s, SCC_10M));
|
|
cell_value(s->unit(), stc.ReadCounterValue(s, SCC_ALL));
|
|
break;
|
|
case SA_VALUE:
|
|
cell_id(s->id());
|
|
cell_name(s->name());
|
|
//cell_value(s->unit(), stc.ReadCounterValue(s, SC_CUR));
|
|
cell_value(s->unit(), stc.ReadCounterValue(s, SCC_10S));
|
|
cell_value(s->unit(), stc.ReadCounterValue(s, SCC_10M));
|
|
cell_dummy();
|
|
break;
|
|
|
|
case SA_CONST:
|
|
cell_id(s->id());
|
|
cell_name(s->name());
|
|
cell_value(s->unit(), stc.ReadCounterValue(s, SCC_10S));
|
|
switch(s->unit())
|
|
{
|
|
case SU_DATETIME:
|
|
case SU_DATE:
|
|
case SU_VERSION:
|
|
case SU_BOOL:
|
|
break;
|
|
default:
|
|
//cell_dummy();
|
|
cell_dummy();
|
|
cell_dummy();
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case SA_EXPR:
|
|
cell_id(s->id());
|
|
cell_name(s->name());
|
|
cell_dummy();
|
|
cell_value(s->unit(), stc.ReadCounterValue(s, SCC_10S));
|
|
cell_value(s->unit(), stc.ReadCounterValue(s, SCC_10M));
|
|
cell_value(s->unit(), stc.ReadCounterValue(s, SCC_ALL));
|
|
break;
|
|
|
|
default:
|
|
row_clear();
|
|
}
|
|
}
|
|
dump_table();
|
|
}
|
|
|
|
void dump_base(void)
|
|
{
|
|
int64_t sc[16];
|
|
int sn;
|
|
|
|
unsigned int i;
|
|
CStatClient::iterator s;
|
|
|
|
stc.CheckPoint();
|
|
|
|
for(i = 0; i < idset.size(); i++)
|
|
{
|
|
s = idset[i];
|
|
row_init();
|
|
sn = stc.GetCountBase(s->id(), sc);
|
|
cell_id(s->id());
|
|
cell_name(s->name());
|
|
cell_nbase(sn);
|
|
for(int n=0; n<sn; n++)
|
|
cell_value(s->unit(), sc[n]);
|
|
}
|
|
dump_table();
|
|
}
|
|
|
|
void create_files(const char *name)
|
|
{
|
|
char buf[256];
|
|
if(statmgr.CreateStatIndex(name, STATIDX, StatDefinition, buf, sizeof(buf)) < 0)
|
|
{
|
|
fprintf(stderr, "Fail to create stat index file: %s\n", buf);
|
|
exit(-3);
|
|
}
|
|
fprintf(stderr, "stat index created: %s\n", STATIDX);
|
|
}
|
|
|
|
void init(const char *name)
|
|
{
|
|
int ret;
|
|
|
|
ret = stc.InitStatInfo(name, STATIDX);
|
|
if(ret < 0)
|
|
{
|
|
fprintf(stderr, "Cannot Initialize StatInfo: %s\n", stc.ErrorMessage());
|
|
exit(-1);
|
|
}
|
|
}
|
|
|
|
void parse_stat_id(int argc, char **argv)
|
|
{
|
|
CStatClient::iterator n;
|
|
|
|
if(argc==0)
|
|
{
|
|
for(n = stc.begin(); n != stc.end(); n++)
|
|
idset.push_back(n);
|
|
return;
|
|
}
|
|
|
|
for(; argc>0; argc--, argv++)
|
|
{
|
|
int s, e;
|
|
switch(sscanf(argv[0], "%d-%d", &s, &e))
|
|
{
|
|
case 2:
|
|
for(n = stc.begin(); n != stc.end(); n++)
|
|
{
|
|
if((int)n->id() >= s && (int)n->id() <= e)
|
|
idset.push_back(n);
|
|
}
|
|
break;
|
|
case 1:
|
|
if((n = stc[s]) != NULL)
|
|
{
|
|
idset.push_back(n);
|
|
break;
|
|
}
|
|
// fall through
|
|
default:
|
|
fprintf(stderr, "Invalid stat id [%s]\n", argv[0]);
|
|
exit(-4);
|
|
}
|
|
}
|
|
}
|
|
|
|
void parse_sample_id(int argc, char **argv)
|
|
{
|
|
CStatClient::iterator n;
|
|
|
|
if(argc==0)
|
|
{
|
|
for(n = stc.begin(); n != stc.end(); n++)
|
|
if(n->issample())
|
|
idset.push_back(n);
|
|
return;
|
|
}
|
|
|
|
for(; argc>0; argc--, argv++)
|
|
{
|
|
int s, e;
|
|
switch(sscanf(argv[0], "%d-%d", &s, &e))
|
|
{
|
|
case 2:
|
|
for(n = stc.begin(); n != stc.end(); n++)
|
|
{
|
|
if((int)n->id() >= s && (int)n->id() <= e && n->issample())
|
|
idset.push_back(n);
|
|
}
|
|
break;
|
|
case 1:
|
|
if((n = stc[s]) != NULL && n->issample())
|
|
{
|
|
idset.push_back(n);
|
|
break;
|
|
}
|
|
// fall through
|
|
default:
|
|
fprintf(stderr, "Invalid stat sample id [%s]\n", argv[0]);
|
|
exit(-4);
|
|
}
|
|
}
|
|
}
|
|
|
|
void alter_base(int argc, char **argv)
|
|
{
|
|
CStatClient::iterator n = NULL;
|
|
int64_t sc[16];
|
|
|
|
if(argc==0 || (n=stc[atoi(argv[0])])==NULL)
|
|
{
|
|
fprintf(stderr, "A stat sample id required\n");
|
|
exit(-5);
|
|
}
|
|
argv++, argc--;
|
|
if(argc > 16)
|
|
{
|
|
fprintf(stderr, "number of count base must <= 16\n");
|
|
exit(-5);
|
|
}
|
|
for(int i=0; i<argc; i++)
|
|
sc[i] = strtoll(argv[i], 0, 0);
|
|
int ret = stc.SetCountBase(n->id(), sc, argc);
|
|
if(ret < 0)
|
|
{
|
|
fprintf(stderr, "setbase failed for id: %d\n", n->id());
|
|
exit(-5);
|
|
}
|
|
idset.push_back(n);
|
|
dump_base();
|
|
}
|
|
|
|
void usage(void)
|
|
{
|
|
fprintf(stderr,
|
|
"Usage: stattool [-nct] cmd [args...]\n"
|
|
"options list:\n"
|
|
" -a output hidden id too\n"
|
|
" -r output unformatted data\n"
|
|
" -n Don't output stat name\n"
|
|
" -t use tab seperated format\n"
|
|
" -c use [,] seperated format\n"
|
|
"command list:\n"
|
|
" create\n"
|
|
" dump name [id|id-id]...\n"
|
|
" getbase name [id|id-id]...\n"
|
|
" setbase name id v1 v2...\n"
|
|
);
|
|
exit(-2);
|
|
}
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
argv++, --argc;
|
|
|
|
while(argc > 0 && argv[0][0]=='-')
|
|
{
|
|
const char *p = argv[0];
|
|
char c;
|
|
while((c=*++p))
|
|
{
|
|
switch(c)
|
|
{
|
|
case 'a':
|
|
alldata = 1;
|
|
break;
|
|
case 'b':
|
|
nobase++;
|
|
break;
|
|
case 'r':
|
|
rawdata = 1;
|
|
break;
|
|
case 't':
|
|
outfmt = CTableFormater::FORMAT_TABBED;
|
|
break;
|
|
case 'c':
|
|
outfmt = CTableFormater::FORMAT_COMMA;
|
|
break;
|
|
case 'n':
|
|
outnoname = 1;
|
|
break;
|
|
case 'h':
|
|
case '?':
|
|
default:
|
|
fprintf(stderr, "Unknown options [%c]\n", c);
|
|
usage();
|
|
}
|
|
}
|
|
argv++, --argc;
|
|
}
|
|
|
|
if(argc <= 0)
|
|
usage();
|
|
else if(!strcasecmp(argv[0], "help"))
|
|
usage();
|
|
else if(!strcasecmp(argv[0], "create"))
|
|
{
|
|
if(argc <= 1)
|
|
usage();
|
|
create_files(argv[1]);
|
|
}
|
|
else if(!strcasecmp(argv[0], "dump"))
|
|
{
|
|
if(argc <= 1)
|
|
usage();
|
|
init(argv[1]);
|
|
parse_stat_id(argc-=2, argv+=2);
|
|
dump_data();
|
|
}
|
|
else if(!strcasecmp(argv[0], "getbase"))
|
|
{
|
|
if(argc <= 1)
|
|
usage();
|
|
init(argv[1]);
|
|
parse_sample_id(argc-=2, argv+=2);
|
|
dump_base();
|
|
}
|
|
else if(!strcasecmp(argv[0], "setbase"))
|
|
{
|
|
if(argc <= 1)
|
|
usage();
|
|
init(argv[1]);
|
|
alter_base(argc-=2, argv+=2);
|
|
}
|
|
else if(!strcasecmp(argv[0], "reporter"))
|
|
{
|
|
// if(TTC_DaemonInit (argc, argv) < 0)
|
|
// return -1;
|
|
if(argc <= 2)
|
|
usage();
|
|
init(argv[1]);
|
|
ALARM_REPORTER->SetStatClient(&stc);
|
|
ALARM_REPORTER->SetTimeOut(5);
|
|
RunReporter(stc, argv[2]?:"");
|
|
} else
|
|
usage();
|
|
return 0;
|
|
}
|