- inserted command statistic
- add runscript parameter to environment object - added Arg2Tcl0 function
This commit is contained in:
46
SCinter.c
46
SCinter.c
@ -57,6 +57,7 @@
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <tcl.h>
|
||||
#include <time.h>
|
||||
#include "fortify.h"
|
||||
#include "sics.h"
|
||||
#include "splitter.h"
|
||||
@ -151,6 +152,7 @@ static void freeList(int listID);
|
||||
pNew->pData = pData;
|
||||
pNew->pNext = NULL;
|
||||
pNew->startupOnly = startupOnly;
|
||||
pNew->stat = StatisticsNew(pBueffel);
|
||||
|
||||
/* find end of list */
|
||||
tail = NULL;
|
||||
@ -232,10 +234,14 @@ static void freeList(int listID);
|
||||
{
|
||||
pInterp->pCList = pVictim->pNext;
|
||||
}
|
||||
if (pVictim->stat) {
|
||||
StatisticsKill(pVictim->stat);
|
||||
}
|
||||
free(pVictim);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
#define MAXLEN 256
|
||||
#define MAXCOM 50
|
||||
extern char *stptok(char *s, char *tok, unsigned int toklen, char *brk);
|
||||
@ -252,6 +258,7 @@ extern char *SkipSpace(char *pPtr);
|
||||
char *pPtr;
|
||||
char **argv = NULL;
|
||||
commandContext comCon;
|
||||
Statistics *old;
|
||||
|
||||
|
||||
assert(self);
|
||||
@ -307,7 +314,9 @@ extern char *SkipSpace(char *pPtr);
|
||||
Tcl_ResetResult((Tcl_Interp *)self->pTcl);
|
||||
MacroPush(pCon);
|
||||
pCon->conStatus = 0;
|
||||
old = StatisticsBegin(pCommand->stat);
|
||||
iRet = pCommand->OFunc(pCon, self, pCommand->pData, argc, argv);
|
||||
StatisticsEnd(old);
|
||||
/* If a task is registered with the dev exec then conStatus is HWBusy*/
|
||||
if (pCon->conStatus != HWBusy) {
|
||||
comCon = SCGetContext(pCon);
|
||||
@ -444,29 +453,40 @@ extern char *SkipSpace(char *pPtr);
|
||||
void DeleteInterp(SicsInterp *self)
|
||||
{
|
||||
CommandList *pCurrent = NULL;
|
||||
CommandList *pTemp;
|
||||
CommandList *pTemp, *tail;
|
||||
Tcl_Interp *pTcl = NULL;
|
||||
int i;
|
||||
|
||||
assert(self);
|
||||
self->iDeleting = 1;
|
||||
|
||||
/* delete Commandlist */
|
||||
/* find end of list */
|
||||
tail = NULL;
|
||||
pCurrent = self->pCList;
|
||||
while(pCurrent)
|
||||
while(pCurrent != NULL)
|
||||
{
|
||||
if(pCurrent->KFunc)
|
||||
tail = pCurrent;
|
||||
pCurrent = pCurrent->pNext;
|
||||
}
|
||||
|
||||
/* delete Commandlist (reversed order) */
|
||||
if (tail) {
|
||||
pCurrent = tail;
|
||||
while(pCurrent)
|
||||
{
|
||||
pCurrent->KFunc(pCurrent->pData);
|
||||
if(pCurrent->KFunc)
|
||||
{
|
||||
pCurrent->KFunc(pCurrent->pData);
|
||||
}
|
||||
if(pCurrent->pName)
|
||||
{
|
||||
/* printf("Deleting %s\n",pCurrent->pName); */
|
||||
free(pCurrent->pName);
|
||||
}
|
||||
pTemp = pCurrent->pPrevious;
|
||||
free(pCurrent);
|
||||
pCurrent = pTemp;
|
||||
}
|
||||
if(pCurrent->pName)
|
||||
{
|
||||
/* printf("Deleting %s\n",pCurrent->pName); */
|
||||
free(pCurrent->pName);
|
||||
}
|
||||
pTemp = pCurrent->pNext;
|
||||
free(pCurrent);
|
||||
pCurrent = pTemp;
|
||||
}
|
||||
|
||||
FreeAliasList(&self->AList); /* M.Z. */
|
||||
|
@ -10,6 +10,7 @@
|
||||
#ifndef SICSINTERPRETER
|
||||
#define SICSINTERPRETER
|
||||
#include "Scommon.h"
|
||||
#include "statistics.h"
|
||||
#include <tcl.h>
|
||||
/* M.Z. */
|
||||
#include "definealias.i"
|
||||
@ -31,6 +32,7 @@ typedef struct __Clist {
|
||||
struct __Clist *pNext;
|
||||
struct __Clist *pPrevious;
|
||||
int startupOnly;
|
||||
Statistics *stat;
|
||||
} CommandList;
|
||||
|
||||
typedef struct __SINTER
|
||||
|
@ -71,13 +71,29 @@
|
||||
static long EVIDrive(void *pData, SConnection *pCon, float fVal)
|
||||
{
|
||||
pEVControl self = NULL;
|
||||
int iRet, iCode, i, iFix;
|
||||
int iRet, iCode, i, iFix, savedStatus;
|
||||
char pError[132], pBueffel[256];
|
||||
|
||||
Tcl_Interp *pTcl = NULL;
|
||||
|
||||
self = (pEVControl)pData;
|
||||
assert(self);
|
||||
assert(pCon);
|
||||
|
||||
if (self->runScript != NULL) {
|
||||
savedStatus = GetStatus();
|
||||
SetStatus(eBatch);
|
||||
pTcl = InterpGetTcl(pServ->pSics);
|
||||
snprintf(pBueffel, sizeof(pBueffel), "%s %f", self->runScript, fVal);
|
||||
iRet = Tcl_Eval(pTcl,pBueffel);
|
||||
SetStatus(savedStatus);
|
||||
if(iRet != TCL_OK)
|
||||
{
|
||||
SCPrintf(pCon, eError,
|
||||
"ERROR: %s while processing runscript for %s",
|
||||
pTcl->result,self->pName);
|
||||
}
|
||||
}
|
||||
|
||||
self->fTarget = fVal;
|
||||
self->eMode = EVDrive;
|
||||
self->iStop = 0;
|
||||
@ -848,6 +864,10 @@ static void ErrReport(pEVControl self)
|
||||
{
|
||||
free(self->creationArgs);
|
||||
}
|
||||
if (self->runScript != NULL)
|
||||
{
|
||||
free(self->runScript);
|
||||
}
|
||||
free(self);
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
@ -855,7 +875,7 @@ static void ErrReport(pEVControl self)
|
||||
{
|
||||
char pBueffel[256], pError[132];
|
||||
int iRet;
|
||||
|
||||
|
||||
assert(self);
|
||||
assert(pCon);
|
||||
|
||||
@ -1025,7 +1045,14 @@ static void ErrReport(pEVControl self)
|
||||
snprintf(pBueffel,255,"%s.errorScript = UNDEFINED", self->pName);
|
||||
}
|
||||
SCWrite(pCon,pBueffel, eValue);
|
||||
|
||||
if(self->runScript != NULL)
|
||||
{
|
||||
SCPrintf(pCon, eValue, "%s.runScript = %s", self->pName, self->runScript);
|
||||
}
|
||||
else
|
||||
{
|
||||
SCPrintf(pCon, eValue, "%s.runScript = none", self->pName);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
@ -1161,10 +1188,10 @@ static void ErrReport(pEVControl self)
|
||||
}
|
||||
else /* parameter request */
|
||||
{
|
||||
strtolower(argv[1]);
|
||||
/*
|
||||
catch case of errorScript
|
||||
*/
|
||||
strtolower(argv[1]);
|
||||
if(strcmp(argv[1],"errorscript") == 0)
|
||||
{
|
||||
if(self->errorScript != NULL)
|
||||
@ -1180,6 +1207,22 @@ static void ErrReport(pEVControl self)
|
||||
SCWrite(pCon,pBueffel,eValue);
|
||||
return 1;
|
||||
}
|
||||
/*
|
||||
catch case of runScript
|
||||
*/
|
||||
if(strcmp(argv[1],"runscript") == 0)
|
||||
{
|
||||
if(self->runScript != NULL)
|
||||
{
|
||||
SCPrintf(pCon, eValue,"%s.runScript = %s",self->pName,
|
||||
self->runScript);
|
||||
}
|
||||
else
|
||||
{
|
||||
SCPrintf(pCon, eValue,"%s.runScript = none",self->pName);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/*
|
||||
catch case for drivername
|
||||
*/
|
||||
@ -1208,10 +1251,10 @@ static void ErrReport(pEVControl self)
|
||||
}
|
||||
else /* try to set parameter */
|
||||
{
|
||||
strtolower(argv[1]);
|
||||
/*
|
||||
first catch case of errorScript
|
||||
*/
|
||||
strtolower(argv[1]);
|
||||
if(strcmp(argv[1],"errorscript") == 0)
|
||||
{
|
||||
if(self->errorScript != NULL)
|
||||
@ -1223,6 +1266,24 @@ static void ErrReport(pEVControl self)
|
||||
SCparChange(pCon);
|
||||
return 1;
|
||||
}
|
||||
/*
|
||||
catch case of runScript
|
||||
*/
|
||||
if(strcmp(argv[1],"runscript") == 0)
|
||||
{
|
||||
if(self->runScript != NULL)
|
||||
{
|
||||
free(self->runScript);
|
||||
}
|
||||
if (strcasecmp(argv[2],"none") == 0) {
|
||||
self->runScript = NULL;
|
||||
} else {
|
||||
self->runScript = Arg2Tcl(argc-2,&argv[2],NULL,0);
|
||||
}
|
||||
SCSendOK(pCon);
|
||||
SCparChange(pCon);
|
||||
return 1;
|
||||
}
|
||||
iRet = Tcl_GetDouble(pSics->pTcl,argv[2],&dVal);
|
||||
if(iRet != TCL_OK)
|
||||
{
|
||||
@ -1263,6 +1324,9 @@ static int EVSaveStatus(void *pData, char *name, FILE *fil)
|
||||
if(evc->errorScript != NULL) {
|
||||
fprintf(fil, " %s errorScript %s\n", evc->pName, evc->errorScript);
|
||||
}
|
||||
if(evc->runScript != NULL) {
|
||||
fprintf(fil, " %s runScript %s\n", evc->pName, evc->runScript);
|
||||
}
|
||||
}
|
||||
fprintf(fil, "}\n");
|
||||
}
|
||||
|
@ -54,6 +54,7 @@ $\langle$evdata {\footnotesize ?}$\rangle\equiv$
|
||||
\mbox{}\verb@ int iStop;@\\
|
||||
\mbox{}\verb@ SCStore conn;@\\
|
||||
\mbox{}\verb@ char *creationArgs;@\\
|
||||
\mbox{}\verb@ char *runScript;@\\
|
||||
\mbox{}\verb@ void *pPrivate;@\\
|
||||
\mbox{}\verb@ void (*KillPrivate)(void *pData);@\\
|
||||
\mbox{}\verb@ } EVControl;@\\
|
||||
@ -88,6 +89,10 @@ holding the logging information. Then there is a switch, iWarned, which is
|
||||
used to prevent execessive output on environment controller error handling.
|
||||
iTcl is a boolean stating if the driver used is a proper C language driver
|
||||
or a Tcl driver.
|
||||
creationArgs are the arguments needed to recreate the device. runScript
|
||||
is a script called on every run or drive command. This script is intended
|
||||
to set control parameters depending on the targetValue. The script is
|
||||
called with the target temperature as argument.
|
||||
This is followed by the void pointer for use by a derived
|
||||
class. KillPrivate is a pointer to a function capable of deleting pPrivate
|
||||
properly.
|
||||
|
@ -49,6 +49,7 @@ used by EVControl:
|
||||
int iStop;
|
||||
SCStore conn;
|
||||
char *creationArgs;
|
||||
char *runScript;
|
||||
void *pPrivate;
|
||||
void (*KillPrivate)(void *pData);
|
||||
} EVControl;
|
||||
@ -76,6 +77,10 @@ holding the logging information. Then there is a switch, iWarned, which is
|
||||
used to prevent execessive output on environment controller error handling.
|
||||
iTcl is a boolean stating if the driver used is a proper C language driver
|
||||
or a Tcl driver.
|
||||
creationArgs are the arguments needed to recreate the device. runScript
|
||||
is a script called on every run or drive command. This script is intended
|
||||
to set control parameters depending on the targetValue. The script is
|
||||
called with the target temperature as argument.
|
||||
This is followed by the void pointer for use by a derived
|
||||
class. KillPrivate is a pointer to a function capable of deleting pPrivate
|
||||
properly.
|
||||
|
7
macro.c
7
macro.c
@ -132,7 +132,8 @@
|
||||
char *lastCommand = NULL, comBuffer[132];
|
||||
int iRet = 0,i;
|
||||
int iMacro;
|
||||
|
||||
Statistics *old;
|
||||
|
||||
/* get the datastructures */
|
||||
pSics = (struct __SicsUnknown *)pData;
|
||||
assert(pSics);
|
||||
@ -181,7 +182,9 @@
|
||||
/* invoke */
|
||||
iMacro = SCinMacro(pCon);
|
||||
SCsetMacro(pCon,1);
|
||||
old=StatisticsBegin(pCommand->stat);
|
||||
iRet = pCommand->OFunc(pCon,pSinter,pCommand->pData,margc, myarg);
|
||||
StatisticsEnd(old);
|
||||
SCsetMacro(pCon,iMacro);
|
||||
/*
|
||||
lastUnkown gets deeply stacked with each SICS command exec'd.
|
||||
@ -881,7 +884,7 @@ static int ProtectedExec(ClientData clientData, Tcl_Interp *interp,
|
||||
}
|
||||
|
||||
/* make a string */
|
||||
pCommand = Arg2Tcl(argc,argv,pBueffel,sizeof(pBueffel));
|
||||
pCommand = Arg2Tcl0(argc-1,argv+1,pBueffel,sizeof(pBueffel),self->command);
|
||||
if (!pCommand) {
|
||||
SCWrite(pCon, "ERROR: no more memory", eError);
|
||||
return 0;
|
||||
|
2
make_gen
2
make_gen
@ -30,7 +30,7 @@ SOBJ = network.o ifile.o conman.o SCinter.o splitter.o passwd.o \
|
||||
s_rnge.o sig_die.o gpibcontroller.o $(NIOBJ) mcreader.o mccontrol.o\
|
||||
hmdata.o nxscript.o tclintimpl.o sicsdata.o mcstascounter.o \
|
||||
mcstashm.o initializer.o remob.o tclmotdriv.o protocol.o \
|
||||
sinfox.o sicslist.o cone.o
|
||||
sinfox.o sicslist.o cone.o statistics.o
|
||||
|
||||
MOTOROBJ = motor.o simdriv.o
|
||||
COUNTEROBJ = countdriv.o simcter.o counter.o
|
||||
|
1
ofac.c
1
ofac.c
@ -410,6 +410,7 @@
|
||||
/* insert here initialization routines ... */
|
||||
|
||||
INIT(SiteInit); /* site specific initializations */
|
||||
INIT(StatisticsInit);
|
||||
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
6
remob.c
6
remob.c
@ -534,7 +534,6 @@ int RemobAction(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
float fValue;
|
||||
long lID;
|
||||
char *endp;
|
||||
char *argv0;
|
||||
char *cmd;
|
||||
/*
|
||||
char acce[128], inte[128];
|
||||
@ -559,10 +558,7 @@ int RemobAction(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
snprintf(inte, sizeof(inte), "!%s.interruptmode", remob->name);
|
||||
*/
|
||||
|
||||
argv0 = argv[0];
|
||||
argv[0] = remob->name;
|
||||
cmd = Arg2Tcl(argc, argv, buf, sizeof buf);
|
||||
argv[0] = argv0;
|
||||
cmd = Arg2Tcl0(argc-1, argv+1, buf, sizeof buf, remob->name);
|
||||
if (cmd) {
|
||||
RemTransact(remserver, rc, pCon, cmd, ">", NULL);
|
||||
if (cmd != buf) free(cmd);
|
||||
|
21
splitter.c
21
splitter.c
@ -400,12 +400,18 @@ typedef enum _CharType {eSpace, eNum,eeText,eQuote} CharType;
|
||||
return 1;
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
char *Arg2Tcl(int argc, char *argv[], char *buffer, int buffersize) {
|
||||
int i, l, firstArgToQuote, quote;
|
||||
char *Arg2Tcl0(int argc, char *argv[], char *buffer, int buffersize, char *prepend) {
|
||||
int i, l, firstArgToQuote, quote, prependlen;
|
||||
char ch;
|
||||
char *res, *arg;
|
||||
|
||||
l = 0;
|
||||
if (prepend) {
|
||||
prependlen = strlen(prepend);
|
||||
l = prependlen + 1;
|
||||
} else {
|
||||
prependlen = 0;
|
||||
l = 0;
|
||||
}
|
||||
firstArgToQuote = argc;
|
||||
quote = 0;
|
||||
for (i=0; i<argc; i++) {
|
||||
@ -443,6 +449,11 @@ char *Arg2Tcl(int argc, char *argv[], char *buffer, int buffersize) {
|
||||
if (buffer == NULL) return NULL;
|
||||
}
|
||||
res = buffer;
|
||||
if (prepend) {
|
||||
strcpy(res, prepend);
|
||||
res += prependlen;
|
||||
*res++ = ' ';
|
||||
}
|
||||
for (i=0; i<argc; i++) {
|
||||
if (i >= firstArgToQuote) *res++ = '"';
|
||||
arg = argv[i];
|
||||
@ -464,6 +475,10 @@ char *Arg2Tcl(int argc, char *argv[], char *buffer, int buffersize) {
|
||||
*res='\0';
|
||||
return buffer;
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
char *Arg2Tcl(int argc, char *argv[], char *buffer, int buffersize) {
|
||||
return Arg2Tcl0(argc, argv, buffer, buffersize, NULL);
|
||||
}
|
||||
/*============================================================================
|
||||
|
||||
Testprogram, can be activated by defining MAIN
|
||||
|
@ -87,5 +87,10 @@ typedef struct _TokenEntry {
|
||||
if (result != NULL && result != buffer) free(result);
|
||||
|
||||
!*/
|
||||
|
||||
char *Arg2Tcl0(int argc, char *argv[], char *buffer, int buffersize, char *prepend);
|
||||
/*!
|
||||
This function is added for convenience, and acts similar to Arg2Tcl.
|
||||
If prepend is not NULL, its contents appear untreated before the args.
|
||||
A space is used as separator.
|
||||
!*/
|
||||
#endif
|
||||
|
149
statistics.c
Normal file
149
statistics.c
Normal file
@ -0,0 +1,149 @@
|
||||
#include <sics.h>
|
||||
#include <sys/time.h>
|
||||
#include "statistics.h"
|
||||
|
||||
typedef struct timeval tv_t;
|
||||
|
||||
struct Statistics {
|
||||
tv_t tim;
|
||||
long cnt;
|
||||
char *name;
|
||||
Statistics *next;
|
||||
};
|
||||
|
||||
static Statistics *current;
|
||||
static tv_t last, lastStat;
|
||||
static Statistics *idle = NULL, *list;
|
||||
static int init = 1;
|
||||
/*-----------------------------------------------------------------------*/
|
||||
tv_t timeDif(tv_t t1, tv_t t2) {
|
||||
tv_t result;
|
||||
|
||||
result.tv_usec = t2.tv_usec - t1.tv_usec;
|
||||
result.tv_sec = t2.tv_sec - t1.tv_sec;
|
||||
if (result.tv_usec < 0) {
|
||||
result.tv_usec += 1000000;
|
||||
result.tv_sec --;
|
||||
}
|
||||
if (result.tv_sec < 0) {
|
||||
result.tv_sec += 24*3600;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
/*-----------------------------------------------------------------------*/
|
||||
void timeAdd(tv_t *t1, tv_t t2) {
|
||||
t1->tv_usec += t2.tv_usec;
|
||||
t1->tv_sec += t2.tv_sec + (t1->tv_usec / 1000000);
|
||||
t1->tv_usec %= 1000000;
|
||||
}
|
||||
/*-----------------------------------------------------------------------*/
|
||||
double timeFloat(tv_t t) {
|
||||
return t.tv_sec + 1e-6 * t.tv_usec;
|
||||
}
|
||||
/*-----------------------------------------------------------------------*/
|
||||
int StatisticsCommand(SConnection *con, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]) {
|
||||
Statistics *p;
|
||||
tv_t now;
|
||||
double dif, percent, dt;
|
||||
|
||||
gettimeofday(&now, 0);
|
||||
dif = timeFloat(timeDif(lastStat, now));
|
||||
SCPrintf(con, eStatus, " calls time[%] mean[ms] command");
|
||||
SCPrintf(con, eStatus, "--------------------------------------");
|
||||
for (p = list; p != NULL; p = p->next) {
|
||||
if (dif > 0) {
|
||||
percent = timeFloat(p->tim) * 100 / dif;
|
||||
if (percent > 0) {
|
||||
if (p->cnt > 0) {
|
||||
dt = timeFloat(p->tim) * 1000.0 / p->cnt;
|
||||
} else {
|
||||
dt = 0;
|
||||
}
|
||||
SCPrintf(con, eStatus, "%7ld %7.1f %8.2f %s", p->cnt,
|
||||
percent, dt, p->name);
|
||||
}
|
||||
}
|
||||
p->cnt = 0;
|
||||
p->tim.tv_sec = 0;
|
||||
p->tim.tv_usec = 0;
|
||||
}
|
||||
lastStat = now;
|
||||
return 1;
|
||||
}
|
||||
/*-----------------------------------------------------------------------*/
|
||||
Statistics *StatisticsNew(char *name) {
|
||||
Statistics *new;
|
||||
|
||||
if (init) {
|
||||
gettimeofday(&lastStat, 0);
|
||||
last = lastStat;
|
||||
init = 0;
|
||||
}
|
||||
new = calloc(1,sizeof(*new));
|
||||
if (new) {
|
||||
new->cnt = 0;
|
||||
new->tim.tv_sec = 0;
|
||||
new->tim.tv_usec = 0;
|
||||
new->next = list;
|
||||
new->name = strdup(name);
|
||||
list = new;
|
||||
}
|
||||
return new;
|
||||
}
|
||||
/*-----------------------------------------------------------------------*/
|
||||
void StatisticsKill(Statistics *stat) {
|
||||
Statistics *p, **last;
|
||||
|
||||
/* find in list */
|
||||
last = &list;
|
||||
for (p = list; p != NULL && p != stat; p = p->next) {
|
||||
last = &p->next;
|
||||
}
|
||||
|
||||
/* remove from list */
|
||||
if (p == stat) {
|
||||
*last = p->next;
|
||||
}
|
||||
|
||||
/* kill it */
|
||||
if (stat->name) {
|
||||
free(stat->name);
|
||||
stat->name = NULL;
|
||||
}
|
||||
free(stat);
|
||||
}
|
||||
/*-----------------------------------------------------------------------*/
|
||||
static void StatisticsSet(Statistics *stat) {
|
||||
tv_t now;
|
||||
|
||||
if (stat != NULL) {
|
||||
gettimeofday(&now, 0);
|
||||
timeAdd(¤t->tim, timeDif(last, now));
|
||||
last = now;
|
||||
}
|
||||
current = stat;
|
||||
}
|
||||
/*-----------------------------------------------------------------------*/
|
||||
Statistics *StatisticsBegin(Statistics *stat) {
|
||||
Statistics *res;
|
||||
|
||||
res = current;
|
||||
StatisticsSet(stat);
|
||||
current->cnt ++;
|
||||
return res;
|
||||
}
|
||||
/*-----------------------------------------------------------------------*/
|
||||
void StatisticsEnd(Statistics *stat) {
|
||||
StatisticsSet(stat);
|
||||
}
|
||||
/*-----------------------------------------------------------------------*/
|
||||
void StatisticsInit(void) {
|
||||
if (idle == NULL) {
|
||||
AddCmd("statistics", StatisticsCommand);
|
||||
last = lastStat;
|
||||
idle = StatisticsNew("<idle>");
|
||||
current = idle;
|
||||
}
|
||||
}
|
||||
|
36
statistics.h
Normal file
36
statistics.h
Normal file
@ -0,0 +1,36 @@
|
||||
/* statistics.h
|
||||
|
||||
statistics on the time spend for commands/tasks
|
||||
|
||||
*/
|
||||
|
||||
#ifndef STATISTICS_H
|
||||
#define STATISTICS_H
|
||||
|
||||
typedef struct Statistics Statistics;
|
||||
|
||||
Statistics *StatisticsNew(char *name);
|
||||
/* create a new Statistics item */
|
||||
|
||||
void StatisticsKill(Statistics *s);
|
||||
/* kill item */
|
||||
|
||||
Statistics *StatisticsBegin(Statistics *s);
|
||||
void StatisticsEnd(Statistics *s);
|
||||
/*
|
||||
Switch statistics to item s.
|
||||
|
||||
Typical usage:
|
||||
|
||||
old = StatisticsBegin(thisItem);
|
||||
|
||||
...do work related with thisItem...
|
||||
|
||||
StatisticsEnd(old);
|
||||
*/
|
||||
|
||||
void StatisticsInit(void);
|
||||
|
||||
/* initialize module and activate statistics command */
|
||||
|
||||
#endif
|
@ -162,7 +162,7 @@ int TclIntAction(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
cmd = Arg2Tcl(argc-2, &argv[2],pBuffer,1023);
|
||||
if (cmd) {
|
||||
if(self->fd != NULL){
|
||||
fprintf(self->fd,"%s\n",pBuffer);
|
||||
fprintf(self->fd,"%s\n",cmd);
|
||||
}
|
||||
if (cmd != pBuffer) free(cmd);
|
||||
SCSendOK(pCon);
|
||||
|
Reference in New Issue
Block a user