Merge branch 'master' into maverick

This commit is contained in:
2016-01-26 10:56:19 +01:00
116 changed files with 7295 additions and 1935 deletions

View File

@ -20,19 +20,25 @@
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <unistd.h>
#include "nserver.h" #include "nserver.h"
#include "servlog.h" #include "servlog.h"
extern void KeepStartupCommands(); /* ofac.c */ extern void KeepStartupCommands(); /* ofac.c */
/***************************** Necessary Globals ****************************/ /***************************** Necessary Globals ****************************/
IPair *pSICSOptions = NULL;
pServer pServ = NULL;
/* ========================= Less dreadful file statics =================== */
#define DEFAULTINIFILE "servo.tcl" #define DEFAULTINIFILE "servo.tcl"
int usage(const char *name)
{
fprintf(stderr, "usage: %s [-d] [-nolog] <config.tcl>\n", name);
fprintf(stderr, " -d: daemonize the process\n");
fprintf(stderr, " -nolog: disable log file writing\n");
return 1;
}
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
The Servers Main program. May take one argument: the name of an The Servers Main program. May take one argument: the name of an
initialisation file initialisation file
@ -41,25 +47,54 @@ pServer pServ = NULL;
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
int iRet; int iRet;
int daemonize = 0;
char *file = NULL; char *file = NULL;
int i; int i, firstArg = 1;
extern pServer pServ;
char *argv0;
argv0 = argv[0];
if (argc < 2)
return usage(argv[0]);
/* initialise, will die on you if problems */ /* initialise, will die on you if problems */
for (i = 1; i < argc; i++) {
if (strcmp(argv[i], "-nolog") == 0) { for (i = firstArg; i < argc; i++) {
SICSLogEnable(0); if (argv[i][0] == '-') {
}else if(strcmp(argv[i],"-keepstartup") == 0){ if (strcasecmp(argv[i], "-nolog") == 0) {
KeepStartupCommands(); SICSLogEnable(0);
}else if(strcmp(argv[i],"-keepstartup") == 0){
KeepStartupCommands();
#ifdef SITE_ANSTO
} else if (strcasecmp(argv[i], "-v") == 0) {
extern void SiteReportVersion(void);
SiteReportVersion();
return 0;
#endif
} else if (strcasecmp(argv[i], "-d") == 0) {
daemonize = 1;
} else {
fprintf(stderr, "Unrecognized option ignored: %s\n", argv[i]);
}
} else if (file == NULL) { } else if (file == NULL) {
file = argv[i]; file = argv[i];
} else {
fprintf(stderr, "Unrecognized argument ignored: %s\n", argv[i]);
} }
} }
if (file == NULL)
return usage(argv[0]);
iRet = InitServer(file, &pServ); iRet = InitServer(file, &pServ);
if (!iRet) { if (!iRet) {
printf("Unrecoverable error on server startup, exiting.........\n"); printf("Unrecoverable error on server startup, exiting.........\n");
exit(1); exit(1);
} }
/*
if (daemonize == 1)
daemon(1, 1);
*/
RunServer(pServ); RunServer(pServ);
@ -68,28 +103,3 @@ int main(int argc, char *argv[])
exit(0); exit(0);
} }
/*--------------------------------------------------------------------------*/
SicsInterp *GetInterpreter(void)
{
return pServ->pSics;
}
/*--------------------------------------------------------------------------*/
pExeList GetExecutor(void)
{
return pServ->pExecutor;
}
/*------------------------------------------------------------------------*/
void StopExit(void)
{
if (pServ) {
StopServer(pServ);
}
}
/*-------------------------------------------------------------------------*/
pTaskMan GetTasker(void)
{
return pServ->pTasker;
}

View File

@ -57,6 +57,10 @@ typedef enum {
eLogError /* error message to log: is always written to client */ eLogError /* error message to log: is always written to client */
} OutCode; } OutCode;
const char* OutCodeToTxt(OutCode outcode);
const char* OutCodeToText(OutCode outcode);
int OutCodeFromText(const char *text, OutCode *outcode);
#include "interrupt.h" #include "interrupt.h"
/* define some user rights codes */ /* define some user rights codes */

15
ascon.c
View File

@ -84,6 +84,8 @@ void AsconError(Ascon *a, char *msg, int errorno)
DynStringConcat(a->errmsg, " ("); DynStringConcat(a->errmsg, " (");
DynStringConcat(a->errmsg, state); DynStringConcat(a->errmsg, state);
DynStringConcat(a->errmsg, " state)"); DynStringConcat(a->errmsg, " state)");
DynStringConcat(a->errmsg, " on ");
DynStringConcat(a->errmsg, a->hostport);
} else { } else {
DynStringConcat(a->errmsg, strerror(errorno)); DynStringConcat(a->errmsg, strerror(errorno));
DynStringConcat(a->errmsg, " ("); DynStringConcat(a->errmsg, " (");
@ -91,6 +93,8 @@ void AsconError(Ascon *a, char *msg, int errorno)
DynStringConcat(a->errmsg, " state, "); DynStringConcat(a->errmsg, " state, ");
DynStringConcat(a->errmsg, msg); DynStringConcat(a->errmsg, msg);
DynStringConcat(a->errmsg, ")"); DynStringConcat(a->errmsg, ")");
DynStringConcat(a->errmsg, " on ");
DynStringConcat(a->errmsg, a->hostport);
} }
a->state = AsconFailed; a->state = AsconFailed;
} }
@ -262,8 +266,7 @@ int AsconReadChar(int fd, char *chr)
if (ret <= 0) if (ret <= 0)
return ret; return ret;
ret = recv(fd, chr, 1, 0); ret = recv(fd, chr, 1, 0);
/* PrintChar(*chr); */ /* PrintChar(*chr); fflush(stdout); */
fflush(stdout);
if (ret > 0) if (ret > 0)
return 1; return 1;
if (ret == 0) { if (ret == 0) {
@ -388,6 +391,12 @@ int AsconBaseHandler(Ascon * a)
} }
void AsconInsertProtocol(AsconProtocol *protocol) { void AsconInsertProtocol(AsconProtocol *protocol) {
AsconProtocol *p;
for (p = protocols; p != NULL; p = p->next) {
if (p == protocol)
return;
}
protocol->next = protocols; protocol->next = protocols;
protocols = protocol; protocols = protocol;
} }
@ -812,7 +821,7 @@ char *AsconRead(Ascon * a)
{ {
if (a->noResponse) { if (a->noResponse) {
a->noResponse = 0; a->noResponse = 0;
return ""; return NULL;
} }
if (a->state != AsconIdle) { if (a->state != AsconIdle) {
a->state = AsconIdle; a->state = AsconIdle;

View File

@ -31,16 +31,23 @@ int defaultSendCommand(pAsyncProtocol p, pAsyncTxn txn)
int defaultHandleInput(pAsyncProtocol p, pAsyncTxn txn, int ch) int defaultHandleInput(pAsyncProtocol p, pAsyncTxn txn, int ch)
{ {
const char *term = "\r\n"; const char *term = "\r\n";
if (p->replyTerminator) if (txn->txn_state == 0) {
term = p->replyTerminator; int i;
if (ch == term[txn->txn_state]) for (i = 0; i < 10; ++i)
if (p->replyTerminator[i] && ch == p->replyTerminator[i][0]) {
txn->txn_state = i << 16;
break;
}
}
term = p->replyTerminator[txn->txn_state >> 16];
if (ch == term[txn->txn_state & 0xffff])
++txn->txn_state; ++txn->txn_state;
else else
txn->txn_state = 0; txn->txn_state = 0;
if (txn->inp_idx < txn->inp_len) if (txn->inp_idx < txn->inp_len)
txn->inp_buf[txn->inp_idx++] = ch; txn->inp_buf[txn->inp_idx++] = ch;
if (term[txn->txn_state] == 0) { if (term[txn->txn_state & 0xffff] == 0) {
if (txn->inp_idx < txn->inp_len) if (txn->inp_idx < txn->inp_len)
txn->inp_buf[txn->inp_idx] = '\0'; txn->inp_buf[txn->inp_idx] = '\0';
return AQU_POP_CMD; return AQU_POP_CMD;
@ -64,10 +71,7 @@ int defaultPrepareTxn(pAsyncProtocol p, pAsyncTxn txn, const char *cmd,
term = p->sendTerminator; term = p->sendTerminator;
state = 0; state = 0;
for (i = 0; i < cmd_len; ++i) { for (i = 0; i < cmd_len; ++i) {
if (cmd[i] == 0x00) { /* end of transmission */ if (cmd[i] == term[state]) {
cmd_len = i;
break;
} else if (cmd[i] == term[state]) {
++state; ++state;
continue; continue;
} }
@ -100,14 +104,6 @@ int defaultPrepareTxn(pAsyncProtocol p, pAsyncTxn txn, const char *cmd,
if (txn->inp_buf != NULL) { if (txn->inp_buf != NULL) {
free(txn->inp_buf); free(txn->inp_buf);
} }
txn->inp_buf = malloc(rsp_len);
if (txn->inp_buf == NULL) {
SICSLogWrite("Out of memory in AsyncProtocol::defaultPrepareTxn",
eError);
free(txn->out_buf);
txn->out_buf = NULL;
return 0;
}
txn->inp_len = rsp_len; txn->inp_len = rsp_len;
txn->inp_idx = 0; txn->inp_idx = 0;
txn->txn_state = 0; txn->txn_state = 0;
@ -122,11 +118,15 @@ static void encodeTerminator(char *result, char *terminator)
{ {
if (terminator) if (terminator)
while (*terminator) { while (*terminator) {
*result++ = '0'; if (*terminator <= 32 || *terminator >= 127) {
*result++ = 'x'; *result++ = '0';
*result++ = hex[(*terminator >> 4) & 0xF]; *result++ = 'x';
*result++ = hex[(*terminator) & 0xF]; *result++ = hex[(*terminator >> 4) & 0xF];
++terminator; *result++ = hex[(*terminator) & 0xF];
++terminator;
} else {
*result++ = *terminator++;
}
} }
*result = '\0'; *result = '\0';
return; return;
@ -208,7 +208,6 @@ int AsyncProtocolNoAction(SConnection * pCon, SicsInterp * pSics,
void *pData, int argc, char *argv[]) void *pData, int argc, char *argv[])
{ {
char line[132]; char line[132];
pAsyncProtocol self = (pAsyncProtocol) pData;
snprintf(line, 132, "%s does not understand %s", argv[0], argv[1]); snprintf(line, 132, "%s does not understand %s", argv[0], argv[1]);
SCWrite(pCon, line, eError); SCWrite(pCon, line, eError);
return 0; return 0;
@ -217,7 +216,6 @@ int AsyncProtocolNoAction(SConnection * pCon, SicsInterp * pSics,
int AsyncProtocolAction(SConnection * pCon, SicsInterp * pSics, int AsyncProtocolAction(SConnection * pCon, SicsInterp * pSics,
void *pData, int argc, char *argv[]) void *pData, int argc, char *argv[])
{ {
char line[132];
pAsyncProtocol self = (pAsyncProtocol) pData; pAsyncProtocol self = (pAsyncProtocol) pData;
if (argc > 1) { if (argc > 1) {
/* handle genecic parameters like terminators */ /* handle genecic parameters like terminators */
@ -240,39 +238,54 @@ int AsyncProtocolAction(SConnection * pCon, SicsInterp * pSics,
return 1; return 1;
} else if (strcasecmp(argv[1], "replyterminator") == 0) { } else if (strcasecmp(argv[1], "replyterminator") == 0) {
if (argc > 2) { if (argc > 2) {
char *pPtr = decodeTerminator(argv[2]); int i;
if (pPtr) { for (i = 0; i < 10; ++i)
if (self->replyTerminator) if (self->replyTerminator[i]) {
free(self->replyTerminator); free(self->replyTerminator[i]);
self->replyTerminator = pPtr; self->replyTerminator[i] = NULL;
}
for (i = 0; i < 10 && i < argc - 2; ++i) {
char* pPtr = decodeTerminator(argv[i + 2]);
if (pPtr) {
self->replyTerminator[i] = pPtr;
}
} }
SCSendOK(pCon); SCSendOK(pCon);
} else { } else {
int i;
char term[132]; char term[132];
char line[1024]; char line[1024];
encodeTerminator(term, self->replyTerminator); term[0] = '\0';
sprintf(line, "%s.replyTerminator = \"%s\"", argv[0], term); sprintf(line, "%s.replyTerminator =", argv[0]);
for (i = 0; i < 10; ++i) {
if (self->replyTerminator[i] == NULL)
break;
term[0] = ' ';
term[1] = '"';
encodeTerminator(&term[2], self->replyTerminator[i]);
strcat(term, "\"");
strcat(line, term);
}
SCWrite(pCon, line, eValue); SCWrite(pCon, line, eValue);
} }
return 1; return 1;
} else if (strcasecmp(argv[1], "list") == 0) {
int ac = 2;
char *av[3] = { argv[0], 0, 0 };
av[1] = "sendterminator";
AsyncProtocolAction(pCon, pSics, pData, ac, av);
av[1] = "replyterminator";
AsyncProtocolAction(pCon, pSics, pData, ac, av);
return 1;
} }
} else if (strcasecmp(argv[1], "list") == 0) {
int ac = 2;
char *av[3] = { argv[0], 0, 0 };
av[1] = "sendterminator";
AsyncProtocolAction(pCon, pSics, pData, ac, av);
av[1] = "replyterminator";
AsyncProtocolAction(pCon, pSics, pData, ac, av);
return 1;
}
/* handle any other actions here */ /* handle any other actions here */
}
return AsyncProtocolNoAction(pCon, pSics, pData, argc, argv); return AsyncProtocolNoAction(pCon, pSics, pData, argc, argv);
} }
void defaultKillPrivate(pAsyncProtocol p) void defaultKillPrivate(pAsyncProtocol p)
{ {
if (p->privateData) { if (p->privateData) {
/* TODO: should we do anything? */
free(p->privateData); free(p->privateData);
} }
} }
@ -280,14 +293,23 @@ void defaultKillPrivate(pAsyncProtocol p)
void AsyncProtocolKill(void *pData) void AsyncProtocolKill(void *pData)
{ {
pAsyncProtocol self = (pAsyncProtocol) pData; pAsyncProtocol self = (pAsyncProtocol) pData;
if (self->pDes) int i;
DeleteDescriptor(self->pDes);
if (self->sendTerminator != NULL)
free(self->sendTerminator);
if (self->replyTerminator != NULL)
free(self->replyTerminator);
if (self->killPrivate) if (self->killPrivate)
self->killPrivate(self); self->killPrivate(self);
if (self->pDes)
DeleteDescriptor(self->pDes);
self->pDes = NULL;
if (self->protocolName)
free(self->protocolName);
self->protocolName = NULL;
if (self->sendTerminator != NULL)
free(self->sendTerminator);
self->sendTerminator = NULL;
for (i = 0; i < 10; ++i) {
if (self->replyTerminator[i] != NULL)
free(self->replyTerminator[i]);
self->replyTerminator[i] = NULL;
}
} }
pAsyncProtocol AsyncProtocolCreate(SicsInterp * pSics, pAsyncProtocol AsyncProtocolCreate(SicsInterp * pSics,
@ -322,13 +344,14 @@ pAsyncProtocol AsyncProtocolCreate(SicsInterp * pSics,
AsyncProtocolKill(self); AsyncProtocolKill(self);
return NULL; return NULL;
} }
self->protocolName = strdup(protocolName);
self->sendCommand = defaultSendCommand; self->sendCommand = defaultSendCommand;
self->handleInput = defaultHandleInput; self->handleInput = defaultHandleInput;
self->handleEvent = defaultHandleEvent; self->handleEvent = defaultHandleEvent;
self->prepareTxn = defaultPrepareTxn; self->prepareTxn = defaultPrepareTxn;
self->killPrivate = defaultKillPrivate; self->killPrivate = defaultKillPrivate;
self->sendTerminator = strdup("\r\n"); self->sendTerminator = strdup("\r\n");
self->replyTerminator = strdup("\r\n"); self->replyTerminator[0] = strdup("\r\n");
return self; return self;
} }

View File

@ -26,6 +26,12 @@ typedef enum {
ATX_DISCO = 3 ATX_DISCO = 3
} ATX_STATUS; } ATX_STATUS;
#define AQU_TIMEOUT -1
#define AQU_DISCONNECT -2
#define AQU_RECONNECT -3
#define AQU_RETRY_CMD -4
#define AQU_POP_CMD -5
struct __async_txn { struct __async_txn {
pAsyncUnit unit; /**< unit that transaction is associated with */ pAsyncUnit unit; /**< unit that transaction is associated with */
int txn_state; /**< protocol handler transaction parse state */ int txn_state; /**< protocol handler transaction parse state */
@ -38,6 +44,8 @@ struct __async_txn {
int inp_len; /**< length of input buffer */ int inp_len; /**< length of input buffer */
int inp_idx; /**< index of next character (number already received) */ int inp_idx; /**< index of next character (number already received) */
AsyncTxnHandler handleResponse; /**< Txn response handler of command sender */ AsyncTxnHandler handleResponse; /**< Txn response handler of command sender */
void *proto_private; /**< Protocol Private structure */
void (*kill_private) (pAsyncTxn pTxn); /**< if it needs killing */
void *cntx; /**< opaque context used by command sender */ void *cntx; /**< opaque context used by command sender */
/* The cntx field may be used by protocol handler from sendCommand /* The cntx field may be used by protocol handler from sendCommand
* as long as it is restored when response is complete * as long as it is restored when response is complete
@ -51,7 +59,7 @@ struct __async_protocol {
pObjectDescriptor pDes; pObjectDescriptor pDes;
char *protocolName; char *protocolName;
char *sendTerminator; char *sendTerminator;
char *replyTerminator; char *replyTerminator[10];
void *privateData; void *privateData;
int (*sendCommand) (pAsyncProtocol p, pAsyncTxn txn); int (*sendCommand) (pAsyncProtocol p, pAsyncTxn txn);
int (*handleInput) (pAsyncProtocol p, pAsyncTxn txn, int ch); int (*handleInput) (pAsyncProtocol p, pAsyncTxn txn, int ch);

View File

@ -8,18 +8,20 @@
* single command channel. * single command channel.
* *
* Douglas Clowes, February 2007 * Douglas Clowes, February 2007
* *
*/ */
#include <sys/time.h> #include <sys/time.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#include <netinet/tcp.h> #include <netinet/tcp.h>
#include <netdb.h> #include <netdb.h>
#include <ctype.h>
#include <stdarg.h>
#include <sics.h> #include <sics.h>
#include <rs232controller.h>
#include "network.h" #include "network.h"
#include "asyncqueue.h" #include "asyncqueue.h"
#include "nwatch.h" #include "nwatch.h"
#include <stdbool.h>
typedef struct __async_command AQ_Cmd, *pAQ_Cmd; typedef struct __async_command AQ_Cmd, *pAQ_Cmd;
@ -40,6 +42,9 @@ struct __AsyncUnit {
void *notify_cntx; void *notify_cntx;
}; };
typedef enum { eAsyncIdle, eAsyncWaiting, eAsyncConnecting,
eAsyncConnected } AsyncState;
struct __AsyncQueue { struct __AsyncQueue {
pObjectDescriptor pDes; pObjectDescriptor pDes;
char *queue_name; char *queue_name;
@ -48,6 +53,9 @@ struct __AsyncQueue {
int iDelay; /* intercommand delay in milliseconds */ int iDelay; /* intercommand delay in milliseconds */
int timeout; int timeout;
int retries; int retries;
int retryTimer; /* mSec delay before next retry */
bool translate; /* translate binary output with escaped chars */
bool trace;
struct timeval tvLastCmd; /* time of completion of last command */ struct timeval tvLastCmd; /* time of completion of last command */
int unit_count; /* number of units connected */ int unit_count; /* number of units connected */
pAsyncUnit units; /* head of unit chain */ pAsyncUnit units; /* head of unit chain */
@ -56,12 +64,56 @@ struct __AsyncQueue {
pNWContext nw_ctx; /* NetWait context handle */ pNWContext nw_ctx; /* NetWait context handle */
pNWTimer nw_tmr; /* NetWait timer handle */ pNWTimer nw_tmr; /* NetWait timer handle */
mkChannel *pSock; /* socket address */ mkChannel *pSock; /* socket address */
AsyncState state; /* Queue Connection State */
pAsyncProtocol protocol; pAsyncProtocol protocol;
char *noreply_text;
int noreply_len;
void *context; /**< opaque caller queue context */
}; };
static pAsyncQueue queue_array[FD_SETSIZE]; static pAsyncQueue queue_array[FD_SETSIZE];
static int queue_index = 0; static int queue_index = 0;
static const char *state_name(AsyncState the_state)
{
switch (the_state) {
case eAsyncIdle:
return "eAsyncIdle";
case eAsyncWaiting:
return "eAsyncWaiting";
case eAsyncConnecting:
return "eAsyncConnecting";
case eAsyncConnected:
return "eAsyncConnected";
}
return "<unknown>";
}
/*
* Free the command and transaction structures and their contents
*/
static void free_command(pAQ_Cmd myCmd)
{
if (myCmd) {
pAsyncTxn myTxn = myCmd->tran;
if (myTxn) {
/*
* Allow kill_private to clean it all if it wants
*/
if (myTxn->kill_private)
myTxn->kill_private(myTxn);
if (myTxn->out_buf)
free(myTxn->out_buf);
if (myTxn->inp_buf)
free(myTxn->inp_buf);
if (myTxn->proto_private)
free(myTxn->proto_private);
free(myTxn);
}
free(myCmd);
}
}
/* ---------------------------- Local ------------------------------------ /* ---------------------------- Local ------------------------------------
CreateSocketAdress stolen from Tcl. Thanks to John Ousterhout CreateSocketAdress stolen from Tcl. Thanks to John Ousterhout
*/ */
@ -99,30 +151,175 @@ static int CreateSocketAdress(struct sockaddr_in *sockaddrPtr, /* Socket addres
return 1; return 1;
} }
static int AQ_ClearTimer(pAsyncQueue self) {
if (self->nw_tmr) {
NetWatchRemoveTimer(self->nw_tmr);
self->nw_tmr = 0;
return 1;
}
return 0;
}
static int AQ_SetTimer(pAsyncQueue self, int msecs, pNWCallback callback, void *context) {
int ret = 1;
if (self->nw_tmr) {
ret = AQ_ClearTimer(self);
}
NetWatchRegisterTimer(&self->nw_tmr, msecs, callback, context);
return ret;
}
static void AQ_Purge(pAsyncQueue self)
{
pAQ_Cmd myCmd = self->command_head;
if (self->nw_tmr)
AQ_ClearTimer(self);
gettimeofday(&self->tvLastCmd, NULL);
while (myCmd) {
/* Process any callback */
if (myCmd->tran->handleResponse) {
myCmd->tran->txn_status = ATX_TIMEOUT; /* TODO should be ATX_DISCO */
myCmd->tran->handleResponse(myCmd->tran);
}
/*
* Remove this transaction from the queue
*/
if (myCmd->next) {
self->command_head = myCmd->next;
} else
self->command_head = self->command_tail = NULL;
free_command(myCmd);
myCmd = self->command_head;
}
}
static void AQ_Notify(pAsyncQueue self, int event) static void AQ_Notify(pAsyncQueue self, int event)
{ {
pAsyncUnit unit; pAsyncUnit unit;
if (self->state != eAsyncConnected)
SICSLogPrintf(eStatus, "Function: %s:%s\n", self->queue_name,
__func__);
for (unit = self->units; unit; unit = unit->next) for (unit = self->units; unit; unit = unit->next)
if (unit->notify_func != NULL) if (unit->notify_func != NULL)
unit->notify_func(unit->notify_cntx, event); unit->notify_func(unit->notify_cntx, event);
} }
static int TimedReconnect(void *cntx, int mode)
{
int iRet;
char line[132];
pAsyncQueue self = (pAsyncQueue) cntx;
self->nw_tmr = 0;
if (self->state != eAsyncConnected)
SICSLogPrintf(eStatus, "Function: %s:%s\n", self->queue_name,
__func__);
AQ_Purge(self);
/* TODO: if self->pSock is NULL we haven't connected yet */
iRet = NETReconnect(self->pSock);
/*
* iRet can take the following values:
* -1: The request failed
* 0: The request is still in progress
* +1: The request succeeded
*/
if (iRet <= 0) {
if (iRet < 0) {
snprintf(line, 132, "Failed reconnect on AsyncQueue '%s'",
self->queue_name);
SICSLogWrite(line, eStatus);
/* Timer for retry */
NetWatchSetMode(self->nw_ctx, 0);
/* implement an exponential backoff within limits */
self->retryTimer = 2 * self->retryTimer;
if (self->retryTimer < 125)
self->retryTimer = 125;
if (self->retryTimer > 16000)
self->retryTimer = 16000;
AQ_SetTimer(self, self->retryTimer,
TimedReconnect, self);
SICSLogPrintf(eStatus, "In %s:%s: state %s => eAsyncWaiting\n",
self->queue_name, __func__, state_name(self->state));
self->state = eAsyncWaiting;
} else {
NetWatchSetMode(self->nw_ctx, nwatch_write);
SICSLogPrintf(eStatus, "In %s:%s: state %s => eAsyncConnecting\n",
self->queue_name, __func__, state_name(self->state));
self->state = eAsyncConnecting;
/* await reconnect result in MyCallback */
}
return 1;
}
NetWatchSetMode(self->nw_ctx, nwatch_read);
SICSLogPrintf(eStatus, "In %s:%s: state %s => eAsyncConnected\n",
self->queue_name, __func__, state_name(self->state));
self->state = eAsyncConnected;
snprintf(line, 132, "Reconnect on AsyncQueue '%s'", self->queue_name);
SICSLogWrite(line, eStatus);
AQ_Purge(self);
AQ_Notify(self, AQU_RECONNECT);
return 1;
}
static int AQ_Reconnect(pAsyncQueue self) static int AQ_Reconnect(pAsyncQueue self)
{ {
int iRet; int iRet;
int sock;
int flag = 1;
char line[132]; char line[132];
iRet = NETReconnect(self->pSock); if (self->state != eAsyncConnected)
if (iRet <= 0) { SICSLogPrintf(eStatus, "Function: %s:%s\n", self->queue_name,
snprintf(line, 132, "Disconnect on AsyncQueue '%s'", self->queue_name); __func__);
SICSLogWrite(line, eStatus); /*
* Remove any old timer
*/
if (self->nw_tmr)
AQ_ClearTimer(self);
if (self->state == eAsyncConnected) {
self->state = eAsyncIdle;
SICSLogPrintf(eStatus, "Disconnect on AsyncQueue '%s'", self->queue_name);
AQ_Notify(self, AQU_DISCONNECT); AQ_Notify(self, AQU_DISCONNECT);
AQ_Purge(self);
}
iRet = NETReconnect(self->pSock);
/*
* iRet can take the following values:
* -1: The request failed
* 0: The request is still in progress
* +1: The request succeeded
*/
if (iRet <= 0) {
if (iRet < 0) {
/* Timer for retry */
NetWatchSetMode(self->nw_ctx, 0);
/* implement an exponential backoff within limits */
self->retryTimer = 125; /* initial delay */
AQ_SetTimer(self, self->retryTimer,
TimedReconnect, self);
SICSLogPrintf(eStatus, "In %s:%s: state %s => eAsyncWaiting\n",
self->queue_name, __func__, state_name(self->state));
self->state = eAsyncWaiting;
} else {
NetWatchSetMode(self->nw_ctx, nwatch_write);
SICSLogPrintf(eStatus, "In %s:%s: state %s => eAsyncConnecting\n",
self->queue_name, __func__, state_name(self->state));
self->state = eAsyncConnecting;
/* await reconnect result in MyCallback */
}
return iRet; return iRet;
} }
NetWatchSetMode(self->nw_ctx, nwatch_read);
SICSLogPrintf(eStatus, "In %s:%s: state %s => eAsyncConnected\n",
self->queue_name, __func__, state_name(self->state));
self->state = eAsyncConnected;
snprintf(line, 132, "Reconnect on AsyncQueue '%s'", self->queue_name); snprintf(line, 132, "Reconnect on AsyncQueue '%s'", self->queue_name);
SICSLogWrite(line, eStatus); SICSLogWrite(line, eStatus);
AQ_Purge(self);
AQ_Notify(self, AQU_RECONNECT); AQ_Notify(self, AQU_RECONNECT);
return 1; return 1;
} }
@ -135,7 +332,11 @@ static int StartCommand(pAsyncQueue self)
{ {
pAQ_Cmd myCmd = self->command_head; pAQ_Cmd myCmd = self->command_head;
mkChannel *sock = self->pSock; mkChannel *sock = self->pSock;
int iRet = 0;
if (self->state != eAsyncConnected)
SICSLogPrintf(eStatus, "Function: %s:%s\n", self->queue_name,
__func__);
if (myCmd == NULL) if (myCmd == NULL)
return OKOK; return OKOK;
@ -143,7 +344,7 @@ static int StartCommand(pAsyncQueue self)
* Remove any old command timeout timer * Remove any old command timeout timer
*/ */
if (self->nw_tmr) if (self->nw_tmr)
NetWatchRemoveTimer(self->nw_tmr); AQ_ClearTimer(self);
/* /*
* Implement the inter-command delay * Implement the inter-command delay
@ -164,7 +365,7 @@ static int StartCommand(pAsyncQueue self)
int delay = when.tv_sec - now.tv_sec; int delay = when.tv_sec - now.tv_sec;
delay *= 1000; delay *= 1000;
delay += (when.tv_usec - now.tv_usec + (1000 - 1)) / 1000; delay += (when.tv_usec - now.tv_usec + (1000 - 1)) / 1000;
NetWatchRegisterTimer(&self->nw_tmr, delay, DelayedStart, self); AQ_SetTimer(self, delay, DelayedStart, self);
return OKOK; return OKOK;
} }
} }
@ -172,33 +373,56 @@ static int StartCommand(pAsyncQueue self)
/* /*
* Discard any input before sending command * Discard any input before sending command
*/ */
while (NETAvailable(sock, 0)) { if (NETAvailable(sock, 0)) {
/* TODO: handle unsolicited input */ while (NETAvailable(sock, 0)) {
char reply[1]; /* TODO: handle unsolicited input */
int iRet; char reply[128];
iRet = NETRead(sock, reply, 1, 0); iRet = NETRead(sock, reply, 128, 0);
if (iRet < 0) { /* EOF */ if (iRet < 0) { /* EOF */
iRet = AQ_Reconnect(self); iRet = AQ_Reconnect(self);
if (iRet <= 0) {
myCmd->tran->txn_state = ATX_DISCO;
if (myCmd->tran->handleResponse) {
myCmd->tran->handleResponse(myCmd->tran);
}
PopCommand(self);
return 0; return 0;
} else if (iRet > 0) {
struct timeval tv;
gettimeofday(&tv, NULL);
SICSLogTimePrintf(eError, &tv,
"ERROR: %d unsolicited chars in AsyncQueue %s",
iRet, self->queue_name);
SICSLogWriteHexTime(reply, iRet, eError, &tv);
} }
} }
} }
myCmd->tran->txn_status = ATX_ACTIVE;
if (self->protocol->sendCommand) {
iRet = self->protocol->sendCommand(self->protocol, myCmd->tran);
} else {
pAsyncTxn txn = myCmd->tran;
iRet = AsyncUnitWrite(txn->unit, txn->out_buf, txn->out_len);
if (iRet < 0)
iRet = 0;
else
iRet = 1;
}
/*
* Handle case of no response expected
*/
if (myCmd->tran->inp_len == 0 || myCmd->tran->inp_buf == NULL) {
myCmd->tran->txn_status = ATX_COMPLETE;
return PopCommand(self);
}
if (iRet > 0)
if (myCmd->tran->txn_status == ATX_COMPLETE)
return PopCommand(self);
/* /*
* Add a new command timeout timer * Add a new command timeout timer
*/ */
if (myCmd->timeout > 0) if (myCmd->timeout > 0)
NetWatchRegisterTimer(&self->nw_tmr, myCmd->timeout, AQ_SetTimer(self, myCmd->timeout,
CommandTimeout, self); CommandTimeout, self);
else else
NetWatchRegisterTimer(&self->nw_tmr, 30000, CommandTimeout, self); AQ_SetTimer(self, 30000, CommandTimeout, self);
myCmd->active = 1; myCmd->active = 1;
return self->protocol->sendCommand(self->protocol, myCmd->tran); return iRet;
} }
static int QueCommandHead(pAsyncQueue self, pAQ_Cmd cmd) static int QueCommandHead(pAsyncQueue self, pAQ_Cmd cmd)
@ -239,13 +463,17 @@ static int QueCommand(pAsyncQueue self, pAQ_Cmd cmd)
self->command_tail = cmd; self->command_tail = cmd;
return 1; return 1;
} }
static int PopCommand(pAsyncQueue self) static int PopCommand(pAsyncQueue self)
{ {
pAQ_Cmd myCmd = self->command_head; pAQ_Cmd myCmd = self->command_head;
if (self->nw_tmr) if (self->nw_tmr)
NetWatchRemoveTimer(self->nw_tmr); AQ_ClearTimer(self);
self->nw_tmr = 0;
gettimeofday(&self->tvLastCmd, NULL); gettimeofday(&self->tvLastCmd, NULL);
/* Process any callback */
if (myCmd->tran->handleResponse)
myCmd->tran->handleResponse(myCmd->tran);
/* /*
* If this is not the last in queue, start transmission * If this is not the last in queue, start transmission
*/ */
@ -255,10 +483,7 @@ static int PopCommand(pAsyncQueue self)
StartCommand(self); StartCommand(self);
} else } else
self->command_head = self->command_tail = NULL; self->command_head = self->command_tail = NULL;
free(myCmd->tran->out_buf); free_command(myCmd);
free(myCmd->tran->inp_buf);
free(myCmd->tran);
free(myCmd);
return 1; return 1;
} }
@ -267,6 +492,13 @@ static int CommandTimeout(void *cntx, int mode)
pAsyncQueue self = (pAsyncQueue) cntx; pAsyncQueue self = (pAsyncQueue) cntx;
pAQ_Cmd myCmd = self->command_head; pAQ_Cmd myCmd = self->command_head;
self->nw_tmr = 0; self->nw_tmr = 0;
if (self->trace) {
struct timeval tv;
gettimeofday(&tv, NULL);
SICSLogTimePrintf(eLog, &tv,
"Timeout Trace on AsyncQueue %s", self->queue_name);
SICSLogWriteHexTime(myCmd->tran->inp_buf, myCmd->tran->inp_idx, eLog, &tv);
}
if (myCmd->retries > 0) { if (myCmd->retries > 0) {
--myCmd->retries; --myCmd->retries;
StartCommand(self); StartCommand(self);
@ -276,8 +508,6 @@ static int CommandTimeout(void *cntx, int mode)
self->protocol->handleEvent(self->protocol, myCmd->tran, self->protocol->handleEvent(self->protocol, myCmd->tran,
AQU_TIMEOUT); AQU_TIMEOUT);
if (iRet == AQU_POP_CMD) { if (iRet == AQU_POP_CMD) {
if (myCmd->tran->handleResponse)
myCmd->tran->handleResponse(myCmd->tran);
PopCommand(self); /* remove command */ PopCommand(self); /* remove command */
} else if (iRet == AQU_RETRY_CMD) } else if (iRet == AQU_RETRY_CMD)
StartCommand(self); /* restart command */ StartCommand(self); /* restart command */
@ -290,6 +520,9 @@ static int CommandTimeout(void *cntx, int mode)
static int DelayedStart(void *cntx, int mode) static int DelayedStart(void *cntx, int mode)
{ {
pAsyncQueue self = (pAsyncQueue) cntx; pAsyncQueue self = (pAsyncQueue) cntx;
if (self->state != eAsyncConnected)
SICSLogPrintf(eStatus, "Function: %s:%s\n", self->queue_name,
__func__);
self->nw_tmr = 0; self->nw_tmr = 0;
StartCommand(self); StartCommand(self);
return 1; return 1;
@ -299,27 +532,18 @@ static int MyCallback(void *context, int mode)
{ {
pAsyncQueue self = (pAsyncQueue) context; pAsyncQueue self = (pAsyncQueue) context;
if (self->state != eAsyncConnected)
SICSLogPrintf(eStatus, "Function: %s:%s\n", self->queue_name,
__func__);
if (mode & nwatch_read) { if (mode & nwatch_read) {
int iRet; int iRet;
char reply[1]; char reply[100];
iRet = NETRead(self->pSock, reply, 1, 0); iRet = NETRead(self->pSock, reply, 100, 0);
/* printf(" iRet, char = %d, %d\n", iRet, (int)reply[0]); */
if (iRet < 0) { /* EOF */ if (iRet < 0) { /* EOF */
iRet = AQ_Reconnect(self); iRet = AQ_Reconnect(self);
if (iRet <= 0) { if (iRet <= 0)
/* changed to call handleResponse with a bad status code: MK
*/
pAQ_Cmd myCmd = self->command_head;
if (myCmd) {
myCmd->tran->txn_state = ATX_DISCO;
if (myCmd->tran->handleResponse) {
myCmd->tran->handleResponse(myCmd->tran);
}
PopCommand(self);
}
return iRet; return iRet;
}
/* restart the command */ /* restart the command */
StartCommand(self); StartCommand(self);
return 1; return 1;
@ -327,22 +551,74 @@ static int MyCallback(void *context, int mode)
if (iRet == 0) { /* TODO: timeout or error */ if (iRet == 0) { /* TODO: timeout or error */
return 0; return 0;
} else { } else {
int nchars = iRet;
int i = 0;
pAQ_Cmd myCmd = self->command_head; pAQ_Cmd myCmd = self->command_head;
if (myCmd) { if (myCmd) {
iRet = for (i = 0; i < nchars; ++i) {
self->protocol->handleInput(self->protocol, myCmd->tran, iRet =
reply[0]); self->protocol->handleInput(self->protocol, myCmd->tran,
if (iRet == 0 || iRet == AQU_POP_CMD) { /* end of command */ reply[i] & 0xFF);
if (myCmd->tran->handleResponse) if (iRet == 0 || iRet == AQU_POP_CMD) { /* end of command */
myCmd->tran->handleResponse(myCmd->tran); if (self->trace) {
PopCommand(self); struct timeval tv;
} else if (iRet < 0) /* TODO: error */ gettimeofday(&tv, NULL);
; SICSLogTimePrintf(eLog, &tv,
"Input Trace on AsyncQueue %s", self->queue_name);
SICSLogWriteHexTime(myCmd->tran->inp_buf, myCmd->tran->inp_idx, eLog, &tv);
}
PopCommand(self);
break;
} else if (iRet < 0) {
int excess = nchars - 1 - i;
struct timeval tv;
gettimeofday(&tv, NULL);
SICSLogTimePrintf(eError, &tv,
"ERROR: Protocol error %d in AsyncQueue %s",
iRet, self->queue_name);
SICSLogWriteTime("Sent:", eError, &tv);
SICSLogWriteHexTime(myCmd->tran->out_buf, myCmd->tran->out_len, eError, &tv);
SICSLogWriteTime("Received:", eError, &tv);
SICSLogWriteHexTime(myCmd->tran->inp_buf, myCmd->tran->inp_idx, eError, &tv);
SICSLogWriteTime("Processed:", eError, &tv);
SICSLogWriteHexTime(&reply[0], i, eError, &tv);
SICSLogWriteTime("Unprocessed:", eError, &tv);
SICSLogWriteHexTime(&reply[i], excess, eError, &tv);
/* TODO: error */
break;
}
}
if (i < nchars - 1) {
int excess = nchars - 1 - i;
struct timeval tv;
gettimeofday(&tv, NULL);
SICSLogTimePrintf(eError, &tv,
"ERROR: %d excess chars in AsyncQueue %s",
excess, self->queue_name);
SICSLogWriteHexTime(&reply[i], excess, eError, &tv);
/* TODO: handle unsolicited */
}
} else { } else {
int excess = nchars - 1 - i;
struct timeval tv;
gettimeofday(&tv, NULL);
SICSLogTimePrintf(eError, &tv,
"ERROR: %d unsolicited chars in AsyncQueue %s",
excess, self->queue_name);
SICSLogWriteHexTime(&reply[i], excess, eError, &tv);
/* TODO: handle unsolicited input */ /* TODO: handle unsolicited input */
} }
} }
} }
if (mode & nwatch_write) {
char line[132];
SICSLogPrintf(eStatus, "Writeable socket callback on AsyncQueue %s",
self->queue_name);
NetWatchSetMode(self->nw_ctx, nwatch_read);
SICSLogPrintf(eStatus, "In %s:%s: state %s => eAsyncConnected\n",
self->queue_name, __func__, state_name(self->state));
self->state = eAsyncConnected;
}
return 1; return 1;
} }
@ -395,20 +671,43 @@ pAsyncTxn AsyncUnitPrepareTxn(pAsyncUnit unit,
myTxn = (pAsyncTxn) malloc(sizeof(AsyncTxn)); myTxn = (pAsyncTxn) malloc(sizeof(AsyncTxn));
if (myTxn == NULL) { if (myTxn == NULL) {
SICSLogWrite("ERROR: Out of memory in AsyncUnitPrepareTxn", eError); SICSLogWrite("ERROR: Out of memory in AsyncUnitPrepareTxn", eError);
return 0; return NULL;
} }
memset(myTxn, 0, sizeof(AsyncTxn)); memset(myTxn, 0, sizeof(AsyncTxn));
if (unit->queue->noreply_text) {
if (cmd_len > unit->queue->noreply_len
&& strncasecmp(&command[cmd_len - unit->queue->noreply_len],
unit->queue->noreply_text, unit->queue->noreply_len) == 0) {
rsp_len = 0;
cmd_len -= unit->queue->noreply_len;
}
} else {
if (cmd_len > 3 && strncmp(&command[cmd_len - 3], "{0}", 3) == 0) {
rsp_len = 0;
cmd_len -= 3;
}
else if (cmd_len > 11 && strncasecmp(&command[cmd_len - 11], "@@NOREPLY@@", 11) == 0) {
rsp_len = 0;
cmd_len -= 11;
}
}
if (unit->queue->protocol->prepareTxn) { if (unit->queue->protocol->prepareTxn) {
int iRet; int iRet;
myTxn->inp_len = rsp_len; /* allowing protocol to change it */
iRet = iRet =
unit->queue->protocol->prepareTxn(unit->queue->protocol, myTxn, unit->queue->protocol->prepareTxn(unit->queue->protocol, myTxn,
command, cmd_len, rsp_len); command, cmd_len, rsp_len);
if (iRet == 0) {
free(myTxn);
return NULL;
}
rsp_len = myTxn->inp_len; /* allowed protocol to change it */
} else { } else {
myTxn->out_buf = (char *) malloc(cmd_len + 5); myTxn->out_buf = (char *) malloc(cmd_len + 5);
if (myTxn->out_buf == NULL) { if (myTxn->out_buf == NULL) {
SICSLogWrite("ERROR: Out of memory in AsyncUnitPrepareTxn", eError); SICSLogWrite("ERROR: Out of memory in AsyncUnitPrepareTxn", eError);
free(myTxn); free(myTxn);
return 0; return NULL;
} }
memcpy(myTxn->out_buf, command, cmd_len); memcpy(myTxn->out_buf, command, cmd_len);
myTxn->out_len = cmd_len; myTxn->out_len = cmd_len;
@ -423,15 +722,12 @@ pAsyncTxn AsyncUnitPrepareTxn(pAsyncUnit unit,
if (rsp_len == 0) if (rsp_len == 0)
myTxn->inp_buf = NULL; myTxn->inp_buf = NULL;
else { else {
if (myTxn->inp_buf != NULL) {
free(myTxn->inp_buf);
}
myTxn->inp_buf = malloc(rsp_len + 1); myTxn->inp_buf = malloc(rsp_len + 1);
if (myTxn->inp_buf == NULL) { if (myTxn->inp_buf == NULL) {
SICSLogWrite("ERROR: Out of memory in AsyncUnitPrepareTxn", eError); SICSLogWrite("ERROR: Out of memory in AsyncUnitPrepareTxn", eError);
free(myTxn->out_buf); free(myTxn->out_buf);
free(myTxn); free(myTxn);
return 0; return NULL;
} }
memset(myTxn->inp_buf, 0, rsp_len + 1); memset(myTxn->inp_buf, 0, rsp_len + 1);
} }
@ -458,6 +754,7 @@ int AsyncUnitSendTxn(pAsyncUnit unit,
typedef struct txn_s { typedef struct txn_s {
char *transReply; char *transReply;
int transWait; int transWait;
int respLen;
} TXN, *pTXN; } TXN, *pTXN;
/** /**
@ -469,30 +766,33 @@ static int TransCallback(pAsyncTxn pCmd)
int resp_len = pCmd->inp_idx; int resp_len = pCmd->inp_idx;
pTXN self = (pTXN) pCmd->cntx; pTXN self = (pTXN) pCmd->cntx;
if (pCmd->txn_status == ATX_TIMEOUT) { self->respLen = resp_len;
if (resp_len > 0) {
memcpy(self->transReply, resp, resp_len); memcpy(self->transReply, resp, resp_len);
self->transReply[resp_len] = '\0'; self->transReply[resp_len] = '\0';
} else
self->transReply[0] = '\0'; self->transReply[0] = '\0';
if (pCmd->txn_status == ATX_TIMEOUT)
self->transWait = -1; self->transWait = -1;
} else { else
memcpy(self->transReply, resp, resp_len);
self->transReply[resp_len] = '\0';
self->transWait = 0; self->transWait = 0;
}
return 0; return 0;
} }
int AsyncUnitTransact(pAsyncUnit unit, int AsyncUnitTransact(pAsyncUnit unit,
const char *command, int cmd_len, const char *command, int cmd_len,
char *response, int rsp_len) char *response, int *rsp_len)
{ {
TXN txn; TXN txn;
assert(unit); assert(unit);
txn.transReply = response; txn.transReply = response;
txn.respLen = *rsp_len;
txn.transWait = 1; txn.transWait = 1;
AsyncUnitSendTxn(unit, command, cmd_len, TransCallback, &txn, rsp_len); AsyncUnitSendTxn(unit, command, cmd_len, TransCallback, &txn, *rsp_len);
while (txn.transWait == 1) while (txn.transWait == 1)
TaskYield(pServ->pTasker); TaskYield(pServ->pTasker);
*rsp_len = txn.respLen;
if (txn.transWait < 0) if (txn.transWait < 0)
return txn.transWait; return txn.transWait;
return 1; return 1;
@ -505,6 +805,13 @@ int AsyncUnitWrite(pAsyncUnit unit, void *buffer, int buflen)
assert(unit); assert(unit);
assert(unit->queue); assert(unit->queue);
if (buflen > 0) { if (buflen > 0) {
if (unit->queue->trace) {
struct timeval tv;
gettimeofday(&tv, NULL);
SICSLogTimePrintf(eLog, &tv,
"Output Trace on AsyncQueue %s", unit->queue->queue_name);
SICSLogWriteHexTime(buffer, buflen, eLog, &tv);
}
sock = AsyncUnitGetSocket(unit); sock = AsyncUnitGetSocket(unit);
iRet = NETWrite(sock, buffer, buflen); iRet = NETWrite(sock, buffer, buflen);
/* TODO handle errors */ /* TODO handle errors */
@ -593,24 +900,75 @@ int AsyncQueueAction(SConnection * pCon, SicsInterp * pSics,
char line[132]; char line[132];
pAsyncQueue self = (pAsyncQueue) pData; pAsyncQueue self = (pAsyncQueue) pData;
if (argc > 1) { if (argc > 1) {
if (strcasecmp("send", argv[1]) == 0) { if (strcasecmp("send", argv[1]) == 0 || strcasecmp("transact", argv[1]) == 0) {
AsyncUnit myUnit; AsyncUnit myUnit;
char cmd[10240]; char cmd[10240];
char rsp[10240]; char rsp[10240];
int idx = 0; int idx = 0;
int i, j; int i, j, len;
cmd[0] = '\0'; cmd[0] = '\0';
/* Managers only */
if (!SCMatchRights(pCon, usMugger))
return 0;
for (i = 2; i < argc; ++i) { for (i = 2; i < argc; ++i) {
j = snprintf(&cmd[idx], 10240 - idx, "%s%s", if (idx >= 10240)
(i > 2) ? " " : "", argv[i]);
if (j < 0)
break; break;
idx += j; if (i > 2)
cmd[idx++] = ' ';
len = strlen(argv[i]);
for (j = 0; j < len; ++j) {
if (idx >= 10240)
break;
if (argv[i][j] == '\\') {
++j;
if (argv[i][j] == '\\')
cmd[idx++] = '\\';
else if (argv[i][j] == 'r')
cmd[idx++] = '\r';
else if (argv[i][j] == 'n')
cmd[idx++] = '\n';
else if (isdigit(argv[i][j])) {
char *nptr = &argv[i][j];
char *endptr;
long k = strtol(nptr, &endptr, 0);
cmd[idx++] = k;
j += (endptr - nptr);
--j; /* prepare for loop increment */
} else
cmd[idx++] = argv[i][j];
} else
cmd[idx++] = argv[i][j];
}
} }
cmd[idx] = '\0';
memset(&myUnit, 0, sizeof(AsyncUnit)); memset(&myUnit, 0, sizeof(AsyncUnit));
myUnit.queue = self; myUnit.queue = self;
AsyncUnitTransact(&myUnit, cmd, idx, rsp, 10240); len = 10240;
SCWrite(pCon, rsp, eValue); (void) AsyncUnitTransact(&myUnit, cmd, idx, rsp, &len);
/* escape control characters in response */
j = 0;
for (i = 0; i < len; ++i) {
if (j >= 10230)
break;
if (self->translate) {
if (rsp[i] < 32 || rsp[i] >= 127) {
if (rsp[i] == '\r') {
cmd[j++] = '\r';
} else if (rsp[i] == '\n') {
cmd[j++] = '\n';
} else {
j += snprintf(&cmd[j], 6, "\\0x%02x", rsp[i]);
}
} else if (rsp[i] == '\\') {
cmd[j++] = '\\';
cmd[j++] = '\\';
} else
cmd[j++] = rsp[i];
} else
cmd[j++] = rsp[i];
}
cmd[j++] = '\0';
SCWrite(pCon, cmd, eValue);
return 1; return 1;
} }
if (strcasecmp(argv[1], "reconnect") == 0) { if (strcasecmp(argv[1], "reconnect") == 0) {
@ -627,7 +985,7 @@ int AsyncQueueAction(SConnection * pCon, SicsInterp * pSics,
SCWrite(pCon, line, eError); SCWrite(pCon, line, eError);
return 0; return 0;
} else { } else {
if (delay < 0 || delay > 30000) { if (delay < 0 || delay > 300000) {
snprintf(line, 132, "Value out of range: %d", delay); snprintf(line, 132, "Value out of range: %d", delay);
SCWrite(pCon, line, eError); SCWrite(pCon, line, eError);
return 0; return 0;
@ -692,6 +1050,85 @@ int AsyncQueueAction(SConnection * pCon, SicsInterp * pSics,
} }
return OKOK; return OKOK;
} }
if (strcasecmp(argv[1], "translate") == 0) {
if (argc > 2) {
int value;
int iRet;
iRet = sscanf(argv[2], "%d", &value);
if (iRet != 1) {
snprintf(line, 132, "Invalid argument: %s", argv[2]);
SCWrite(pCon, line, eError);
return 0;
} else {
if (value == 0) {
self->translate = false;
return OKOK;
} else if (value == 1) {
self->translate = true;
return OKOK;
}
snprintf(line, 132, "Invalid argument: %s", argv[2]);
SCWrite(pCon, line, eError);
return 0;
}
} else {
snprintf(line, 132, "%s.translate = %d", argv[0], self->translate);
SCWrite(pCon, line, eStatus);
return OKOK;
}
return OKOK;
}
if (strcasecmp(argv[1], "trace") == 0) {
if (argc > 2) {
int value;
int iRet;
iRet = sscanf(argv[2], "%d", &value);
if (iRet != 1) {
snprintf(line, 132, "Invalid argument: %s", argv[2]);
SCWrite(pCon, line, eError);
return 0;
} else {
if (value == 0) {
self->trace = false;
return OKOK;
} else if (value == 1) {
self->trace = true;
return OKOK;
}
snprintf(line, 132, "Invalid argument: %s", argv[2]);
SCWrite(pCon, line, eError);
return 0;
}
} else {
snprintf(line, 132, "%s.trace = %d", argv[0], self->trace);
SCWrite(pCon, line, eStatus);
return OKOK;
}
return OKOK;
}
if (strcasecmp(argv[1], "noreply") == 0) {
if (argc > 2) {
if (self->noreply_text)
free(self->noreply_text);
self->noreply_text = strdup(argv[2]);
self->noreply_len = strlen(argv[2]);
} else {
SCPrintf(pCon, eValue, "%s.noreply = %s", argv[0], self->noreply_text);
}
return OKOK;
}
if (strcasecmp(argv[1], "list") == 0) {
SCPrintf(pCon, eValue, "%s.delay = %d", argv[0], self->iDelay);
SCPrintf(pCon, eValue, "%s.timeout = %d", argv[0], self->timeout);
SCPrintf(pCon, eValue, "%s.retries = %d", argv[0], self->retries);
SCPrintf(pCon, eValue, "%s.translate = %d", argv[0], self->translate);
SCPrintf(pCon, eValue, "%s.trace = %d", argv[0], self->trace);
if (self->noreply_text)
SCPrintf(pCon, eValue, "%s.noreply = %s", argv[0], self->noreply_text);
if (self->protocol && self->protocol->protocolName)
SCPrintf(pCon, eValue, "%s.protocol = %s", argv[0], self->protocol->protocolName);
return OKOK;
}
} }
snprintf(line, 132, "%s does not understand %s", argv[0], argv[1]); snprintf(line, 132, "%s does not understand %s", argv[0], argv[1]);
SCWrite(pCon, line, eError); SCWrite(pCon, line, eError);
@ -741,6 +1178,7 @@ static pAsyncQueue AQ_Create(const char *host, const char *port)
} }
if (self == NULL) { if (self == NULL) {
/* TODO: if channel (self->pSock) is NULL we haven't connected yet, do it later */
if (channel == NULL) if (channel == NULL)
return NULL; return NULL;
@ -760,6 +1198,15 @@ static pAsyncQueue AQ_Create(const char *host, const char *port)
if (i == queue_index) if (i == queue_index)
queue_array[queue_index++] = self; queue_array[queue_index++] = self;
/* TODO: if self->pSock is NULL we haven't connected yet */
#if 0
if (channel == NULL) {
/* TODO: all the rest */
AQ_SetTimer(self, self->retryTimer, TimedReconnect,
self);
}
#endif
return self; return self;
} }
@ -769,6 +1216,7 @@ static int AQ_Init(pAsyncQueue self)
if (self->nw_ctx == NULL) if (self->nw_ctx == NULL)
NetWatchRegisterCallback(&self->nw_ctx, NetWatchRegisterCallback(&self->nw_ctx,
self->pSock->sockid, MyCallback, self); self->pSock->sockid, MyCallback, self);
NetWatchSetMode(self->nw_ctx, nwatch_write | nwatch_read);
return 1; return 1;
} }
@ -784,7 +1232,7 @@ static void AQ_Kill(void *pData)
if (self->nw_ctx) if (self->nw_ctx)
NetWatchRemoveCallback(self->nw_ctx); NetWatchRemoveCallback(self->nw_ctx);
if (self->nw_tmr) if (self->nw_tmr)
NetWatchRemoveTimer(self->nw_tmr); AQ_ClearTimer(self);
if (self->queue_name) if (self->queue_name)
free(self->queue_name); free(self->queue_name);
NETClosePort(self->pSock); NETClosePort(self->pSock);
@ -979,3 +1427,31 @@ pAsyncUnit AsyncUnitFromQueue(pAsyncQueue queue)
result->queue = queue; result->queue = queue;
return result; return result;
} }
void *AsyncUnitSetQueueContext(pAsyncUnit unit, void *cntx)
{
void *hold;
assert(unit);
assert(unit->queue);
hold = unit->queue->context;
unit->queue->context = cntx;
return hold;
}
void *AsyncUnitGetQueueContext(pAsyncUnit unit)
{
assert(unit);
assert(unit->queue);
return unit->queue->context;
}
int AsyncUnitIsQueueConnected(pAsyncUnit unit)
{
assert(unit);
assert(unit->queue);
if (unit && unit->queue)
if (unit->queue->state == eAsyncConnected)
return 1;
return 0;
}

View File

@ -11,12 +11,6 @@
#include "asyncprotocol.h" #include "asyncprotocol.h"
#define AQU_TIMEOUT -1
#define AQU_DISCONNECT -2
#define AQU_RECONNECT -3
#define AQU_RETRY_CMD -4
#define AQU_POP_CMD -5
typedef struct __AsyncQueue AsyncQueue, *pAsyncQueue; typedef struct __AsyncQueue AsyncQueue, *pAsyncQueue;
@ -28,7 +22,7 @@ typedef struct __AsyncQueue AsyncQueue, *pAsyncQueue;
*/ */
int AsyncUnitCreate(const char *queueName, pAsyncUnit * unit); int AsyncUnitCreate(const char *queueName, pAsyncUnit * unit);
/** \brief Get an AsyncUnit from a given AsyncQueue /** \brief Get an AsyncUnit from a given AsyncQueue
* \param queue The AsyncQueue fro which this AsyncUnit is valid * \param queue The AsyncQueue for which this AsyncUnit is valid
* \return a new AsyncUnit or NULL on error * \return a new AsyncUnit or NULL on error
*/ */
pAsyncUnit AsyncUnitFromQueue(pAsyncQueue queue); pAsyncUnit AsyncUnitFromQueue(pAsyncQueue queue);
@ -36,9 +30,13 @@ pAsyncUnit AsyncUnitFromQueue(pAsyncQueue queue);
/** \brief create an AsyncUnit attached to an anonymous AsyncQueue. /** \brief create an AsyncUnit attached to an anonymous AsyncQueue.
* *
* \param host name or address of the target host * \param host name or address of the target host
* \param port number or service name on the target host * \param port number or service name on the target host
* \param unit pointer to the AsyncUnit created on positive return * \param unit pointer to the AsyncUnit created on positive return
* \return positive if successful * \return positive if successful
*
* If <port> is null then <host> points to an existing queue name.
* If a queue exists for <host>/<port>, then that queue is used.
* If neither of the above hold, a new queue is created.
*/ */
int AsyncUnitCreateHost(const char *host, int AsyncUnitCreateHost(const char *host,
const char *port, pAsyncUnit * unit); const char *port, pAsyncUnit * unit);
@ -98,11 +96,12 @@ int AsyncUnitSendTxn(pAsyncUnit unit,
* \param cmd_len length of data in command * \param cmd_len length of data in command
* \param responseHandler function to handle the response * \param responseHandler function to handle the response
* \param context to be used by handler function * \param context to be used by handler function
* \param resp_len maximum length to be allowed for response * \param resp_len [in] maximum length to be allowed for response
* [out] actual length returned
*/ */
int AsyncUnitTransact(pAsyncUnit unit, int AsyncUnitTransact(pAsyncUnit unit,
const char *command, int cmd_len, const char *command, int cmd_len,
char *response, int rsp_len); char *response, int *rsp_len);
/** \brief write to the AsyncQueue file descriptor /** \brief write to the AsyncQueue file descriptor
* *
@ -182,4 +181,16 @@ int AsyncQueueFactory(SConnection * pCon, SicsInterp * pSics,
int AsyncQueueAction(SConnection * pCon, SicsInterp * pSics, int AsyncQueueAction(SConnection * pCon, SicsInterp * pSics,
void *pData, int argc, char *argv[]); void *pData, int argc, char *argv[]);
/** \brief store queue level context
*/
void *AsyncUnitSetQueueContext(pAsyncUnit handle, void *cntx);
/** \brief retrieve queue level context
*/
void *AsyncUnitGetQueueContext(pAsyncUnit handle);
/** \brief return one if queue is connected, zero otherwise
*/
int AsyncUnitIsQueueConnected(pAsyncUnit handle);
#endif /* SICSASYNCQUEUE */ #endif /* SICSASYNCQUEUE */

View File

@ -397,14 +397,20 @@ void ANETprocess(void)
{ {
int i, status, count = 0, socke = 0, length; int i, status, count = 0, socke = 0, length;
fd_set readMask, writeMask; fd_set readMask, writeMask;
struct timeval tmo = { 0, 20 }; struct timeval tmo = { 0, 10000 };
FD_ZERO(&readMask); FD_ZERO(&readMask);
FD_ZERO(&writeMask); FD_ZERO(&writeMask);
for (i = 0; i < noConnections; i++) { for (i = 0; i < noConnections; i++) {
socke = connections[i].socket; socke = connections[i].socket;
FD_SET(socke, &readMask); FD_SET(socke, &readMask);
FD_SET(socke, &writeMask); if (connections[i].writeBuffer != NULL) {
GetRWBufferData(connections[i].writeBuffer, &length);
if (length > 0)
FD_SET(socke, &writeMask);
else
connections[i].lastOpenForWrite = time(NULL);
}
if (socke > count) { if (socke > count) {
count = socke; count = socke;
} }
@ -575,6 +581,7 @@ void *ANETreadPtr(int handle, int *length)
con = findSocketDescriptor(handle); con = findSocketDescriptor(handle);
if (con == NULL) { if (con == NULL) {
*length = 0;
return NULL; return NULL;
} else { } else {
data = GetRWBufferData(con->readBuffer, length); data = GetRWBufferData(con->readBuffer, length);

View File

@ -53,18 +53,19 @@
* modbus-crc: CRC-16-IBM, order: lo,hi * modbus-crc: CRC-16-IBM, order: lo,hi
* keller-crc: CRC-16-IBM, order: hi,lo * keller-crc: CRC-16-IBM, order: hi,lo
* sycon-crc: sort of mod 256 checksum, byte stuffing included (no float allowed) * sycon-crc: sort of mod 256 checksum, byte stuffing included (no float allowed)
* chksum-crc: simple 8bit checksum
*/ */
typedef enum {intType, hexType, floatType, typedef enum {intType, hexType, floatType,
skipType, codeType, crcType, dumpType, errorType} BinDataType; skipType, codeType, crcType, dumpType, errorType} BinDataType;
// dumpType, errorType must be the last items // dumpType, errorType must be the last items
typedef enum {modbusCrc, kellerCrc, rsportCrc, syconCrc} CrcAlgorithm; typedef enum {modbusCrc, kellerCrc, rsportCrc, syconCrc, chksumCrc} CrcAlgorithm;
typedef struct { typedef struct {
CrcAlgorithm crcAlgorithm; CrcAlgorithm crcAlgorithm;
pDynString inp; pDynString inp;
char *nextFmt; char *nextFmt; // position of next format token
pDynString result; pDynString result;
int expectedChars; int expectedChars;
BinDataType type; BinDataType type;
@ -135,6 +136,23 @@ static int calc_crc8(char *inp, int inpLen)
} }
return crc; return crc;
} }
/*----------------------------------------------------------------------------*/
static int calc_chksum(char *inp, int inpLen)
{
/** simple 8bit checksum
*/
unsigned char crc = 0;
unsigned char data;
int n;
while (inpLen--) {
data = *(unsigned char *) inp;
crc += data;
inp++;
}
return crc;
}
/*----------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------*/
int BinReadItem(Ascon *a) { int BinReadItem(Ascon *a) {
@ -154,7 +172,11 @@ int BinReadItem(Ascon *a) {
if (strcasecmp(item, "crc") == 0) { if (strcasecmp(item, "crc") == 0) {
p->type = crcType; p->type = crcType;
p->expectedChars = 2; if (p->crcAlgorithm == chksumCrc) {
p->expectedChars = 1;
} else {
p->expectedChars = 2;
}
p->nextFmt += valen; p->nextFmt += valen;
return 1; return 1;
} else if (strncasecmp(item, "int", 3) == 0) { } else if (strncasecmp(item, "int", 3) == 0) {
@ -281,6 +303,10 @@ int BinHandler(Ascon *a) {
DynStringConcatChar(dyn, crc % 256); DynStringConcatChar(dyn, crc % 256);
DynStringConcatChar(dyn, crc / 256); DynStringConcatChar(dyn, crc / 256);
break; break;
case chksumCrc:
crc = calc_chksum(GetCharArray(dyn), l);
DynStringConcatChar(dyn, crc % 256);
break;
case rsportCrc: case rsportCrc:
crc = calc_crc8(GetCharArray(dyn), l); crc = calc_crc8(GetCharArray(dyn), l);
DynStringConcatChar(dyn, crc); DynStringConcatChar(dyn, crc);
@ -509,6 +535,11 @@ int BinHandler(Ascon *a) {
DynStringConcat(p->result, "badCRC "); DynStringConcat(p->result, "badCRC ");
} }
break; break;
case chksumCrc:
if (calc_chksum(str, l-1) != (unsigned char)str[l-1]) {
DynStringConcat(p->result, "badCRC ");
}
break;
case kellerCrc: case kellerCrc:
i = str[l-2]; i = str[l-2];
str[l-2] = str[l-1]; str[l-2] = str[l-1];
@ -560,6 +591,8 @@ static int BinInit(Ascon * a, SConnection * con, int argc, char *argv[])
p->crcAlgorithm = syconCrc; p->crcAlgorithm = syconCrc;
} else if (strcasecmp(argv[2], "rsport-crc") == 0) { } else if (strcasecmp(argv[2], "rsport-crc") == 0) {
p->crcAlgorithm = rsportCrc; p->crcAlgorithm = rsportCrc;
} else if (strcasecmp(argv[2], "chksum-crc") == 0) {
p->crcAlgorithm = chksumCrc;
} else if (strcasecmp(argv[2], "modbus-crc") != 0) { } else if (strcasecmp(argv[2], "modbus-crc") != 0) {
SCPrintf(con, eError, "ERROR: unknown crc-algorithm %s", argv[2]); SCPrintf(con, eError, "ERROR: unknown crc-algorithm %s", argv[2]);
a->private = NULL; a->private = NULL;

View File

@ -271,6 +271,36 @@ int RemoveCallback2(pICallBack self, void *pUserData)
return 1; return 1;
} }
/*--------------------------------------------------------------------------*/
/*
* Remove callback in context -
* if the callback function matches and the user function returns zero
*/
int RemoveCallbackUsr(pICallBack self, SICSCallBack pFunc, int (*userfunc)(const void* pContext, const void* pUserData), void *pCtx)
{
pCallBackItem pItem;
if (!CheckPointer(self))
{
return 0;
}
pItem = self->head;
while (pItem != NULL) {
if (pItem->pFunc == pFunc) {
if(userfunc(pCtx, pItem->pUserData) == 0) {
if (debug) {
printf("Killing callback at %p\n", self);
}
pItem->killFlag = 1;
}
}
pItem = pItem->next;
}
cleanCallbackList(self);
return 1;
}
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
int RemoveCallbackCon(pICallBack self, SConnection * con) int RemoveCallbackCon(pICallBack self, SConnection * con)
{ {

View File

@ -177,7 +177,7 @@ static void KillAdapter(void *pData)
if (self->pParName){ if (self->pParName){
free(self->pParName); free(self->pParName);
} }
free(self); free(self);
} }

View File

@ -538,7 +538,7 @@ int CommandLog(SConnection * pCon, SicsInterp * pSics, void *pData,
if (iCompact > 0) if (iCompact > 0)
iIntervall = 0; iIntervall = 0;
} }
SCPrintf(pCon, eValue, "%s.compact [sec] = %d", argv[0], iCompact); SCPrintf(pCon, eValue, "%s.compact [sec] = %d", argv[0], (int)iCompact);
return 1; return 1;
} else if (strcmp(argv[1], "close") == 0) { /* close command */ } else if (strcmp(argv[1], "close") == 0) { /* close command */
fclose(fd); fclose(fd);

View File

@ -17,6 +17,7 @@ typedef struct __CONFVIRTMOT {
float targetValue; float targetValue;
int targetReached; int targetReached;
int posCount; int posCount;
double last_report_time;
char scriptError[512]; char scriptError[512];
int parseOK; int parseOK;
}ConfigurableVirtualMotor, *pConfigurableVirtualMotor; }ConfigurableVirtualMotor, *pConfigurableVirtualMotor;

View File

@ -35,7 +35,11 @@
#include "confvirtmot.h" #include "confvirtmot.h"
#include "confvirtmot.i" #include "confvirtmot.i"
#define BAD_VALUE (-9999.99)
extern char *stptok(char *s, char *t, int len, char *brk); extern char *stptok(char *s, char *t, int len, char *brk);
extern int CheckMotiMatch(const void* context, const void* pUserData);
extern double DoubleTime(void);
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
An internal data structure which holds information required to control An internal data structure which holds information required to control
@ -214,6 +218,7 @@ static long ConfSetValue(void *pData, SConnection * pCon, float newValue)
self->targetValue = newValue; self->targetValue = newValue;
self->targetReached = 0; self->targetReached = 0;
self->posCount = 0; self->posCount = 0;
self->last_report_time = 0.0;
status = startMotorList(self, pCon); status = startMotorList(self, pCon);
if (status != OKOK) { if (status != OKOK) {
@ -303,7 +308,6 @@ static int InterestCallback(int iEvent, void *pEvent, void *pUser)
return -1; return -1;
} }
if (pInfo->lastValue != pEventData->fVal) { if (pInfo->lastValue != pEventData->fVal) {
pInfo->lastValue = pEventData->fVal; pInfo->lastValue = pEventData->fVal;
(pInfo->pCon)->conEventType = POSITION; (pInfo->pCon)->conEventType = POSITION;
@ -370,12 +374,14 @@ static int ConfCheckStatus(void *pData, SConnection * pCon)
InvokeCallBack(self->pCall, MOTDRIVE, &event); InvokeCallBack(self->pCall, MOTDRIVE, &event);
} }
} else if (result == HWBusy) { } else if (result == HWBusy) {
self->posCount++; double current_time, skip_time;
if (self->posCount >= 10 /*ObVal(self->ParArray,MOVECOUNT) */ ) { current_time = DoubleTime();
skip_time = 0.500;
if (self->last_report_time + skip_time <= current_time) {
event.pName = self->name; event.pName = self->name;
event.fVal = self->pDriv->GetValue(self, pCon); event.fVal = self->pDriv->GetValue(self, pCon);
InvokeCallBack(self->pCall, MOTDRIVE, &event); InvokeCallBack(self->pCall, MOTDRIVE, &event);
self->posCount = 0; self->last_report_time = current_time;
} }
} }
return result; return result;
@ -431,7 +437,7 @@ static void checkMotorValues(pConfigurableVirtualMotor self,
static float ConfGetValue(void *pData, SConnection * pCon) static float ConfGetValue(void *pData, SConnection * pCon)
{ {
pConfigurableVirtualMotor self = (pConfigurableVirtualMotor) pData; pConfigurableVirtualMotor self = (pConfigurableVirtualMotor) pData;
float currentValue = -9999.99; float currentValue = BAD_VALUE;
assert(self != NULL); assert(self != NULL);
@ -493,6 +499,14 @@ static void KillConfigurableVirtualMotor(void *data)
free(self->state); free(self->state);
self->state = NULL; self->state = NULL;
} }
if (self->pCall != NULL) {
DeleteCallBackInterface(self->pCall);
self->pCall = NULL;
}
if (self->pDriv != NULL) {
free(self->pDriv);
self->pDriv = NULL;
}
free(self); free(self);
self = NULL; self = NULL;
} }
@ -521,6 +535,7 @@ int MakeConfigurableVirtualMotor(SConnection * pCon, SicsInterp * pSics,
pNew->name = strdup(argv[1]); pNew->name = strdup(argv[1]);
pNew->posCount = 0; pNew->posCount = 0;
pNew->last_report_time = 0.0;
pNew->pDes = CreateDescriptor("ConfigurableVirtualMotor"); pNew->pDes = CreateDescriptor("ConfigurableVirtualMotor");
pNew->pDriv = CreateDrivableInterface(); pNew->pDriv = CreateDrivableInterface();
pNew->motorList = LLDcreate(sizeof(RealMotor)); pNew->motorList = LLDcreate(sizeof(RealMotor));
@ -570,7 +585,6 @@ int ConfigurableVirtualMotorAction(SConnection * pCon, SicsInterp * pSics,
pConfigurableVirtualMotor self = NULL; pConfigurableVirtualMotor self = NULL;
char pBueffel[512]; char pBueffel[512];
float value; float value;
int iRet;
long lID; long lID;
pRegisteredInfo pRegInfo = NULL; pRegisteredInfo pRegInfo = NULL;
@ -685,12 +699,17 @@ int ConfigurableVirtualMotorAction(SConnection * pCon, SicsInterp * pSics,
} }
pRegInfo->lastValue = value; pRegInfo->lastValue = value;
RemoveCallbackUsr(self->pCall, InterestCallback, CheckMotiMatch, pCon); /* only this one */
lID = RegisterCallback(self->pCall, MOTDRIVE, lID = RegisterCallback(self->pCall, MOTDRIVE,
InterestCallback, pRegInfo, KillInfo); InterestCallback, pRegInfo, KillInfo);
SCSendOK(pCon); SCSendOK(pCon);
return 1; return 1;
} else if(strcmp(argv[1],"uninterest") == 0) {
RemoveCallbackUsr(self->pCall, InterestCallback, CheckMotiMatch, pCon);
SCSendOK(pCon);
return 1;
} else { } else {
snprintf(pBueffel, 5120, "ERROR: subcommand %s to %s unknown", snprintf(pBueffel, sizeof(pBueffel), "ERROR: subcommand %s to %s unknown",
argv[1], argv[0]); argv[1], argv[0]);
SCWrite(pCon, pBueffel, eError); SCWrite(pCon, pBueffel, eError);
return 0; return 0;

View File

@ -22,6 +22,7 @@ typedef struct __CONFVIRTMOT {
float targetValue; float targetValue;
int targetReached; int targetReached;
int posCount; int posCount;
double last_report_time;
char scriptError[512]; char scriptError[512];
int parseOK; int parseOK;
}ConfigurableVirtualMotor, *pConfigurableVirtualMotor; }ConfigurableVirtualMotor, *pConfigurableVirtualMotor;

326
conman.c
View File

@ -3,7 +3,7 @@
Connection management for SICS. This is one the core files for Connection management for SICS. This is one the core files for
SICS. Does a lot. See the descriptions with individual functions SICS. Does a lot. See the descriptions with individual functions
below. below.
Mark Koennecke, October 1996 Mark Koennecke, October 1996
@ -73,6 +73,16 @@
#include "statusfile.h" #include "statusfile.h"
#include "sicshipadaba.h" #include "sicshipadaba.h"
#include "protocol.h" #include "protocol.h"
#include "sicsvar.h"
#include <json/json.h>
/*
Greetings from protocol.c for SCLogWrite...
*/
extern struct json_object *mkJSON_Object(SConnection * pCon, char *pBuffer,
int iOut);
/* /*
#define UUDEB 1 #define UUDEB 1
define UUDEB , for buffer writing for checking encoding */ define UUDEB , for buffer writing for checking encoding */
@ -81,6 +91,13 @@ extern pServer pServ;
#include "outcode.c" /* text for OutCode */ #include "outcode.c" /* text for OutCode */
int KillCapture(SConnection * pCon);
int LogCapture(SConnection * pCon, SicsInterp * pInter, void *pData,
int argc, char *argv[]);
int LogOutput(SConnection * pCon, SicsInterp * pInter, void *pData,
int argc, char *argv[]);
/*------ Max Size of Command Stack */ /*------ Max Size of Command Stack */
#define MAXSTACK 1024 #define MAXSTACK 1024
@ -108,6 +125,24 @@ struct SCStore {
long macroStack; long macroStack;
commandContext cc; commandContext cc;
}; };
/*
* This will return the value of a SICS int variable called "sicsdebug"
* If sicsdebug is not defined it will return 1
* TODO Maybe define debugging levels.
*
* return 0=debug off, 1=debug on or sicsdebug not defined.
*/
int sicsdebug() {
pSicsVariable debug;
debug = FindVariable(pServ->pSics, "sicsdebug");
if (debug) {
return debug->iVal;
} else {
return 1;
}
}
/*===========================================================================*/ /*===========================================================================*/
static char *ConName(long ident) static char *ConName(long ident)
{ {
@ -229,6 +264,7 @@ static SConnection *CreateConnection(SicsInterp * pSics)
pRes->conStart = time(NULL); pRes->conStart = time(NULL);
pRes->write = SCNormalWrite; pRes->write = SCNormalWrite;
pRes->runLevel = RUNDRIVE; pRes->runLevel = RUNDRIVE;
pRes->remote = 0;
/* initialise context variables */ /* initialise context variables */
pRes->iCmdCtr = 0; pRes->iCmdCtr = 0;
@ -461,6 +497,7 @@ SConnection *SCCopyConnection(SConnection * pCon)
result->iList = -1; result->iList = -1;
result->runLevel = pCon->runLevel; result->runLevel = pCon->runLevel;
result->data = pCon->data; result->data = pCon->data;
result->remote = pCon->remote;
return result; return result;
} }
@ -650,7 +687,7 @@ int SCPrintf(SConnection * self, int iOut, char *fmt, ...)
va_list ap; va_list ap;
char buf[256]; char buf[256];
char *dyn; char *dyn;
int l; unsigned int l;
int res; int res;
va_start(ap, fmt); va_start(ap, fmt);
@ -779,6 +816,64 @@ static int testAndWriteSocket(SConnection * pCon, char *buffer, int iOut)
return 0; return 0;
} }
/*--------------------------------------------------------------------------*/
static int isOK(const char *buffer)
{
if ((buffer[0] == 'O' && buffer[1] == 'K')
&& (buffer[2] == '\0' || buffer[2] == '\r' || buffer[2] == '\n'))
return 1;
return 0;
}
/*--------------------------------------------------------------------------*/
static void testAndWriteSICSLog(SConnection * self, char *buffer, int iOut)
{
char tp;
/* We don't want to log the "OK" messages */
if (isOK(buffer))
return;
if (SCinMacro(self)) {
tp = 'M';
if (sicsdebug())
tp = 'D';
} else
tp = 'N';
switch (iOut) {
case eStatus:
case eStart:
case eFinish:
case eEvent:
case eHdbValue:
case eHdbEvent:
case eLog:
case eLogError:
case eError:
case eWarning:
/* Log it */
SICSLogWriteCode(buffer, iOut, tp);
return;
case eValue:
if (sicsdebug() || !SCinMacro(self)) {
/* Log it */
SICSLogWriteCode(buffer, iOut, tp);
return;
} else {
/* Suppressed */
#if 0
tp = tolower(tp);
SICSLogWriteCode(buffer, iOut, tp);
#endif
return;
}
break;
default:
printf("Unrecognized ouput code %d in testAndWriteSICSLog: FIXME!!!\n", iOut);
SICSLogWriteCode(buffer, iOut, tp);
return;
}
}
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
int SCNormalWrite(SConnection * self, char *buffer, int iOut) int SCNormalWrite(SConnection * self, char *buffer, int iOut)
{ {
@ -793,7 +888,11 @@ int SCNormalWrite(SConnection * self, char *buffer, int iOut)
} }
/* log it for any case */ /* log it for any case */
SICSLogWrite(buffer, iOut); #if 0
SICSLogWrite(buffer, iOut);
#else
testAndWriteSICSLog(self, buffer, iOut);
#endif
testAndWriteCommandLog(self, buffer, iOut); testAndWriteCommandLog(self, buffer, iOut);
@ -992,13 +1091,14 @@ int SCPureSockWrite(SConnection * self, char *buffer, int iOut)
{ {
char pBueffel[1024]; char pBueffel[1024];
char *pPtr; char *pPtr;
json_object *myJson = NULL;
/* for commandlog tail */ /* for commandlog tail */
if (!VerifyConnection(self)) { if (!VerifyConnection(self)) {
return 0; return 0;
} }
if(self->iProtocolID == 5) { if(self->iProtocolID == PROTACT) { /* act */
if (strlen(buffer) + 30 > 1024) { if (strlen(buffer) + 30 > 1024) {
pPtr = (char *) malloc((strlen(buffer) + 30) * sizeof(char)); pPtr = (char *) malloc((strlen(buffer) + 30) * sizeof(char));
memset(pPtr, 0, strlen(buffer) + 20); memset(pPtr, 0, strlen(buffer) + 20);
@ -1010,6 +1110,12 @@ int SCPureSockWrite(SConnection * self, char *buffer, int iOut)
if(pPtr != pBueffel){ if(pPtr != pBueffel){
free(pPtr); free(pPtr);
} }
} else if(self->iProtocolID == PROTJSON) {
myJson = mkJSON_Object(self,buffer,iOut);
if(myJson != NULL){
SCDoSockWrite(self,(char *)json_object_to_json_string(myJson));
json_object_put(myJson);
}
} else { } else {
testAndWriteSocket(self, buffer, iOut); testAndWriteSocket(self, buffer, iOut);
} }
@ -1023,6 +1129,7 @@ int SCLogWrite(SConnection * self, char *buffer, int iOut)
{ {
char pBueffel[1024]; char pBueffel[1024];
char *pPtr; char *pPtr;
json_object *myJson = NULL;
if (!VerifyConnection(self)) { if (!VerifyConnection(self)) {
return 0; return 0;
@ -1031,7 +1138,7 @@ int SCLogWrite(SConnection * self, char *buffer, int iOut)
WriteToCommandLogId(NULL, self->sockHandle, buffer); WriteToCommandLogId(NULL, self->sockHandle, buffer);
SetSendingConnection(NULL); SetSendingConnection(NULL);
if(self->iProtocolID == 5) { if(self->iProtocolID == PROTACT) { /* act */
if (strlen(buffer) + 30 > 1024) { if (strlen(buffer) + 30 > 1024) {
pPtr = (char *) malloc((strlen(buffer) + 30) * sizeof(char)); pPtr = (char *) malloc((strlen(buffer) + 30) * sizeof(char));
memset(pPtr, 0, strlen(buffer) + 20); memset(pPtr, 0, strlen(buffer) + 20);
@ -1043,7 +1150,7 @@ int SCLogWrite(SConnection * self, char *buffer, int iOut)
if(pPtr != pBueffel){ if(pPtr != pBueffel){
free(pPtr); free(pPtr);
} }
} else if(self->iProtocolID == 2) { } else if(self->iProtocolID == PROTCODE) { /* withcode */
if (strlen(buffer) + 30 > 1024) { if (strlen(buffer) + 30 > 1024) {
pPtr = (char *) malloc((strlen(buffer) + 30) * sizeof(char)); pPtr = (char *) malloc((strlen(buffer) + 30) * sizeof(char));
memset(pPtr, 0, strlen(buffer) + 20); memset(pPtr, 0, strlen(buffer) + 20);
@ -1055,6 +1162,12 @@ int SCLogWrite(SConnection * self, char *buffer, int iOut)
if(pPtr != pBueffel){ if(pPtr != pBueffel){
free(pPtr); free(pPtr);
} }
} else if(self->iProtocolID == PROTJSON) { /* json */
myJson = mkJSON_Object(self,buffer,iOut);
if(myJson != NULL){
SCDoSockWrite(self,(char *)json_object_to_json_string(myJson));
json_object_put(myJson);
}
} else { } else {
testAndWriteSocket(self, buffer, iOut); testAndWriteSocket(self, buffer, iOut);
} }
@ -1235,7 +1348,7 @@ int SCWriteZipped(SConnection * self, char *pName, void *pData,
memset(outBuf, 0, 65536); memset(outBuf, 0, 65536);
protocolID = GetProtocolID(self); protocolID = GetProtocolID(self);
if (protocolID == 5) { if (protocolID == PROTACT) {
cc = SCGetContext(self); cc = SCGetContext(self);
sprintf(outBuf, "SICSBIN ZIP %s %d %d\r\n", pName, sprintf(outBuf, "SICSBIN ZIP %s %d %d\r\n", pName,
compressedLength, cc.transID); compressedLength, cc.transID);
@ -1310,7 +1423,7 @@ int SCWriteBinary(SConnection * self, char *pName, void *pData,
memset(outBuf, 0, 65536); memset(outBuf, 0, 65536);
protocolID = GetProtocolID(self); protocolID = GetProtocolID(self);
if (protocolID == 5) { if (protocolID == PROTACT) {
cc = SCGetContext(self); cc = SCGetContext(self);
sprintf(outBuf, "SICSBIN BIN %s %d %d\r\n", pName, sprintf(outBuf, "SICSBIN BIN %s %d %d\r\n", pName,
iDataLen, cc.transID); iDataLen, cc.transID);
@ -1416,7 +1529,7 @@ int SCWriteZippedOld(SConnection * self, char *pName, void *pData,
memset(outBuf, 0, 65536); memset(outBuf, 0, 65536);
protocolID = GetProtocolID(self); protocolID = GetProtocolID(self);
if (protocolID == 5) { if (protocolID == PROTACT) {
cc = SCGetContext(self); cc = SCGetContext(self);
sprintf(outBuf, "SICSBIN ZIP %s %d %d\r\n", pName, sprintf(outBuf, "SICSBIN ZIP %s %d %d\r\n", pName,
compressedLength, cc.transID); compressedLength, cc.transID);
@ -1742,7 +1855,7 @@ int SCInvoke(SConnection * self, SicsInterp * pInter, char *pCommand)
memset(pBueffel, 0, 80); memset(pBueffel, 0, 80);
stptok(trim(pCommand), pBueffel, 79, " "); stptok(trim(pCommand), pBueffel, 79, " ");
self->iCmdCtr++; self->iCmdCtr++;
if (999999 < self->iCmdCtr) { if (self->iCmdCtr > 99998) {
self->iCmdCtr = 0; self->iCmdCtr = 0;
} }
self->transID = self->iCmdCtr; self->transID = self->iCmdCtr;
@ -1768,6 +1881,7 @@ int SCInvoke(SConnection * self, SicsInterp * pInter, char *pCommand)
config File Filename Logs to another file config File Filename Logs to another file
config output normal | withcode | ACT Sets output mode config output normal | withcode | ACT Sets output mode
config listen 0 | 1 enables commandlog listen mode config listen 0 | 1 enables commandlog listen mode
config remote sets the remote connection flag
---------------------------------------------------------------------------*/ ---------------------------------------------------------------------------*/
int ConfigCon(SConnection * pCon, SicsInterp * pSics, void *pData, int ConfigCon(SConnection * pCon, SicsInterp * pSics, void *pData,
@ -1825,7 +1939,11 @@ int ConfigCon(SConnection * pCon, SicsInterp * pSics, void *pData,
SCSendOK(pCon); SCSendOK(pCon);
return 1; return 1;
} }
} } else if(strcmp(argv[1],"remote") == 0) {
pMaster->remote = 1;
pCon->remote = 1;
return 1;
}
/* check no or args */ /* check no or args */
if (argc < 3) { if (argc < 3) {
@ -2137,6 +2255,190 @@ int ConSicsAction(SConnection * pCon, SicsInterp * pSics, void *pData,
return 0; return 0;
} }
static void hookFunc(const char *pText, OutCode eOut, void*pData)
{
SConnection *pCon = (SConnection *) pData;
int text_len = strlen(pText);
char txt[5];
if (!VerifyConnection(pCon)) {
return;
}
if (!ANETvalidHandle(pCon->sockHandle)) {
return;
}
snprintf(txt, 5, "%3s:", OutCodeToTxt(eOut));
ANETwrite(pCon->sockHandle, txt, 4);
ANETwrite(pCon->sockHandle, (char *)pText, text_len);
if (pText[text_len - 1] != '\n')
ANETwrite(pCon->sockHandle, "\n", 1);
}
int KillCapture(SConnection * pCon)
{
RemSICSLogHook(pCon);
return 1;
}
/* ------------------------------------------------------------------------
the command function:
Syntax:
Kill kills all logging
Log OutCode starts loggin OutCode events
All starts logging all events
-------------------------------------------------------------------------- */
int LogCapture(SConnection * pCon, SicsInterp * pSics, void *pData,
int argc, char *argv[])
{
SConnection * pConMaster;
char pBueffel[512];
int i;
pConMaster = SCfindMaster(pCon);
if (pConMaster == NULL)
return 0;
/* check no af args */
if (argc < 2) {
snprintf(pBueffel,sizeof(pBueffel)-1, "Insufficient number of arguments to %s", argv[0]);
SCWrite(pCon, pBueffel, eError);
return 0;
}
argtolower(argc, argv);
/* Branch according to argv[1] */
if (strcmp(argv[1], "kill") == 0 || strcmp(argv[1], "none") == 0) {
SCPrintf(pCon, eLog, "getlog %s", argv[1]);
KillCapture(pConMaster);
return 1;
} else if (strcmp(argv[1], "what") == 0) {
unsigned int code_bits = 0;
pDynString buffer;
code_bits = (1 << iNoCodes) - 1;
buffer = CreateDynString(100, 100);
for (i = 0; i < iNoCodes; ++i) {
if (code_bits & (1 << i)) {
if (GetDynStringLength(buffer) > 0)
DynStringConcatChar(buffer, ',');
DynStringConcat(buffer, (char *)OutCodeToTxt(i));
}
}
SCPrintf(pCon, eLog, "getlog %s", GetCharArray(buffer));
DeleteDynString(buffer);
return 1;
} else if (strcmp(argv[1], "list") == 0) {
unsigned int code_bits = 0;
pDynString buffer;
code_bits = GetSICSLogHook(pConMaster);
if (code_bits == 0) {
SCPrintf(pCon, eLog, "getlog none");
return 1;
}
buffer = CreateDynString(100, 100);
for (i = 0; i < iNoCodes; ++i) {
if (code_bits & (1 << i)) {
if (GetDynStringLength(buffer) > 0)
DynStringConcatChar(buffer, ',');
DynStringConcat(buffer, (char *)OutCodeToTxt(i));
}
}
SCPrintf(pCon, eLog, "getlog %s", GetCharArray(buffer));
DeleteDynString(buffer);
return 1;
} else if (strcmp(argv[1], "all") == 0) {
SCPrintf(pCon, eLog, "getlog all");
AddSICSLogHook(hookFunc, "all", pConMaster);
return 1;
} else if (argc == 2) {
/* must be outcode, try find it */
SCPrintf(pCon, eLog, "getlog %s", argv[1]);
AddSICSLogHook(hookFunc, argv[1], pConMaster);
return 1;
} else {
/* make it a list */
int i;
size_t len;
char *pBuff;
for (i = 1, len = 0; i < argc; ++i)
len += strlen(argv[i]) + 1;
if (len > sizeof(pBueffel))
pBuff = malloc(len);
else
pBuff = pBueffel;
if (pBuff == NULL) {
SCWrite(pCon, "Out of memory in LogCapture\n", eError);
return 1;
}
for (i = 1, len = 0; i < argc; ++i) {
if (i > 1)
pBuff[len++] = ',';
strcpy(&pBuff[len], argv[i]);
len += strlen(argv[i]);
}
SCPrintf(pCon, eLog, "getlog %s", pBuff);
AddSICSLogHook(hookFunc, pBuff, pConMaster);
if (pBuff != pBueffel)
free(pBuff);
return 1;
}
return 0;
}
/* ------------------------------------------------------------------------
the command function:
Syntax:
LogOutput [OutCode] <text>
Logs <text> with outcode OutCode default eLog
-------------------------------------------------------------------------- */
int LogOutput(SConnection * pCon, SicsInterp * pSics, void *pData,
int argc, char *argv[])
{
char pBueffel[512];
char *pBuff;
int i, result, start;
size_t len;
OutCode outcode;
/* check no af args */
if (argc < 2) {
snprintf(pBueffel,sizeof(pBueffel)-1, "Insufficient number of arguments to %s", argv[0]);
SCWrite(pCon, pBueffel, eError);
return 0;
}
/* assume default eLog unless told otherwise */
start = 1;
outcode = eLog;
if (argv[1][0] == '@') {
result = OutCodeFromText(&argv[1][1], &outcode);
if (result >= 0) {
start = 2;
}
}
/* make it a string */
for (i = start, len = 0; i < argc; ++i)
len += strlen(argv[i]) + 1;
if (len > sizeof(pBueffel))
pBuff = malloc(len+10);
else
pBuff = pBueffel;
if (pBuff == NULL) {
SCWrite(pCon, "Out of memory in LogOutput\n", eError);
return 1;
}
for (i = start, len = 0; i < argc; ++i) {
if (i > start)
pBuff[len++] = ' ';
strcpy(&pBuff[len], argv[i]);
len += strlen(argv[i]);
}
SICSLogWrite(pBuff, outcode);
if (pBuff != pBueffel)
free(pBuff);
return 1;
}
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
int SCTaskFunction(void *pData) int SCTaskFunction(void *pData)
{ {
@ -2207,7 +2509,7 @@ int SCTaskFunction(void *pData)
pPassword = strtok(NULL, " \t\r\n"); pPassword = strtok(NULL, " \t\r\n");
iRet = IsValidUser(pUser, pPassword); iRet = IsValidUser(pUser, pPassword);
if (iRet >= 0) { if (iRet >= 0) {
SCWrite(self, "Login OK", eError); SCWrite(self, "Login OK", eLog);
self->iLogin = 1; self->iLogin = 1;
SCSetRights(self, iRet); SCSetRights(self, iRet);
pHost[0] = '\0'; pHost[0] = '\0';

View File

@ -71,6 +71,7 @@ typedef struct __SConnection {
pCosta pStack; /* stack of pending commands */ pCosta pStack; /* stack of pending commands */
int contextStack; /* context stack: may go? */ int contextStack; /* context stack: may go? */
mkChannel *pSock; /* for temporary backwards compatability */ mkChannel *pSock; /* for temporary backwards compatability */
int remote; /* true if this is a remote object connection */
} SConnection; } SConnection;
#include "nserver.h" #include "nserver.h"
@ -92,7 +93,14 @@ SConnection *GetSendingConnection(void);
/* ***************************** I/O ************************************** */ /* ***************************** I/O ************************************** */
void SCSetOutputClass(SConnection * self, int iClass); void SCSetOutputClass(SConnection * self, int iClass);
int SCWrite(SConnection * self, char *pBuffer, int iOut); int SCWrite(SConnection * self, char *pBuffer, int iOut);
int SCPrintf(SConnection * self, int iOut, char *fmt, ...); #if __GNUC__ > 2
#define G_GNUC_PRINTF( format_idx, arg_idx ) \
__attribute__((__format__ (__printf__, format_idx, arg_idx)))
#else
#define G_GNUC_PRINTF( format_idx, arg_idx )
#endif
int SCPrintf(SConnection * self, int iOut, char *fmt, ...) G_GNUC_PRINTF (3, 4);
#undef G_GNUC_PRINTF
int SCRead(SConnection * self, char *pBuffer, int iBufLen); int SCRead(SConnection * self, char *pBuffer, int iBufLen);
int SCPrompt(SConnection * pCon, char *pPrompt, char *pResult, int iLen); int SCPrompt(SConnection * pCon, char *pPrompt, char *pResult, int iLen);
int SCPromptTMO(SConnection * pCon, char *pPrompt, char *pResult, int iLen, int timeout); int SCPromptTMO(SConnection * pCon, char *pPrompt, char *pResult, int iLen, int timeout);

16
costa.c
View File

@ -108,10 +108,6 @@ int CostaTop(pCosta self, char *pCommand)
assert(self); assert(self);
/* check for lock */
if (self->iLock) {
return 0;
}
/* check Size */ /* check Size */
if (self->iCount >= self->iMaxSize) { if (self->iCount >= self->iMaxSize) {
return 0; return 0;
@ -138,11 +134,6 @@ int CostaBottom(pCosta self, char *pCommand)
int iRet, iRes = 1; int iRet, iRes = 1;
assert(self); assert(self);
/* check for lock */
if (self->iLock) {
return 0;
}
/* do not want 0 commands */ /* do not want 0 commands */
if (strlen(pCommand) < 1) { if (strlen(pCommand) < 1) {
return 1; return 1;
@ -187,3 +178,10 @@ void CostaUnlock(pCosta self)
{ {
self->iLock = 0; self->iLock = 0;
} }
/*--------------------------------------------------------------------------*/
int CostaLocked(pCosta self)
{
return self->iLock;
}

View File

@ -25,5 +25,6 @@ int CostaPop(pCosta self, char **pPtr);
/*----------------------------------------------------------------------*/ /*----------------------------------------------------------------------*/
void CostaLock(pCosta self); void CostaLock(pCosta self);
void CostaUnlock(pCosta self); void CostaUnlock(pCosta self);
int CostaLocked(pCosta self);
#endif #endif

View File

@ -1,6 +1,6 @@
/*------------------------------------------------------------------------ /*------------------------------------------------------------------------
G E N C O U N T G E N C O U N T
Some general stuff for handling a CounterDriver. Some general stuff for handling a CounterDriver.
@ -61,6 +61,7 @@ pCounterDriver CreateCounterDriver(char *name, char *type)
pRes->fPreset = 1000.; pRes->fPreset = 1000.;
pRes->fTime = 0.; pRes->fTime = 0.;
pRes->iNoOfMonitors = 0; pRes->iNoOfMonitors = 0;
pRes->iControlMonitor = 0;
pRes->iPause = 0; pRes->iPause = 0;
pRes->Start = NULL; pRes->Start = NULL;
pRes->GetStatus = NULL; pRes->GetStatus = NULL;

View File

@ -1,20 +1,20 @@
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
C O U N T E R D R I V E R C O U N T E R D R I V E R
This is the interface to a Sics-Counter driver. This means a This is the interface to a Sics-Counter driver. This means a
single counter managing possibly several monitors in one go. single counter managing possibly several monitors in one go.
A counter can run for a predefined time or until a predefined A counter can run for a predefined time or until a predefined
monitor count has been reached. monitor count has been reached.
Mark Koennecke, January 1996 Mark Koennecke, January 1996
General parameter setting added: General parameter setting added:
Mark Koennecke, April 1999 Mark Koennecke, April 1999
copyright: see implementation file. copyright: see implementation file.
---------------------------------------------------------------------------*/ ---------------------------------------------------------------------------*/
#ifndef SICSCOUNTERDRIVER #ifndef SICSCOUNTERDRIVER
#define SICSCOUNTERDRIVER #define SICSCOUNTERDRIVER
@ -42,6 +42,7 @@ typedef struct __COUNTER {
float fLastCurrent; float fLastCurrent;
float fTime; float fTime;
int iNoOfMonitors; int iNoOfMonitors;
int iControlMonitor;
long lCounts[MAXCOUNT]; long lCounts[MAXCOUNT];
int iPause; int iPause;
int iErrorCode; int iErrorCode;

View File

@ -551,7 +551,7 @@ static int SetCounterModeImpl(pCounter self, CounterMode eNew)
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
CounterMode GetCounterMode(pCounter self) CounterMode GetCounterMode(pCounter self)
{ {
return self->getMode(self); return self->getMode(self);
} }
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
static CounterMode GetCounterModeImpl(pCounter self) static CounterMode GetCounterModeImpl(pCounter self)
@ -562,7 +562,7 @@ static CounterMode GetCounterModeImpl(pCounter self)
/*------------------------------------------------------------------------*/ /*------------------------------------------------------------------------*/
int GetNMonitor(pCounter self) int GetNMonitor(pCounter self)
{ {
return self->getNMonitor(self); return self->getNMonitor(self);
} }
/*------------------------------------------------------------------------*/ /*------------------------------------------------------------------------*/
static int GetNMonitorImpl(pCounter self) static int GetNMonitorImpl(pCounter self)
@ -571,13 +571,28 @@ static int GetNMonitorImpl(pCounter self)
return self->pDriv->iNoOfMonitors; return self->pDriv->iNoOfMonitors;
} }
int GetControlMonitor(pCounter self)
{
return self->pDriv->iControlMonitor;
}
int SetControlMonitor(pCounter self, int channel)
{
int maxchan = self->pDriv->iNoOfMonitors - 1;
if (channel < 0 || channel > maxchan) {
return 0;
}
self->pDriv->iControlMonitor = channel;
return 1;
}
#ifdef NONINTF #ifdef NONINTF
extern float nintf(float f); extern float nintf(float f);
#endif #endif
/*------------------------------------------------------------------------*/ /*------------------------------------------------------------------------*/
int SetCounterPreset(pCounter self, float fVal) int SetCounterPreset(pCounter self, float fVal)
{ {
return self->setPreset(self,fVal); return self->setPreset(self,fVal);
} }
/*------------------------------------------------------------------------*/ /*------------------------------------------------------------------------*/
static int SetCounterPresetImpl(pCounter self, float fVal) static int SetCounterPresetImpl(pCounter self, float fVal)
@ -603,17 +618,17 @@ static int SetCounterPresetImpl(pCounter self, float fVal)
/*------------------------------------------------------------------------*/ /*------------------------------------------------------------------------*/
float GetCounterPreset(pCounter self) float GetCounterPreset(pCounter self)
{ {
return self->getPreset(self); return self->getPreset(self);
} }
/*------------------------------------------------------------------------*/ /*------------------------------------------------------------------------*/
float GetControlValue(pCounter self) float GetControlValue(pCounter self)
{ {
return self->getControlValue(self); return self->getControlValue(self);
} }
/*------------------------------------------------------------------------*/ /*------------------------------------------------------------------------*/
static float GetControlValueImpl(pCounter self) static float GetControlValueImpl(pCounter self)
{ {
return self->pDriv->fLastCurrent; return self->pDriv->fLastCurrent;
} }
/*------------------------------------------------------------------------*/ /*------------------------------------------------------------------------*/
static float GetCounterPresetImpl(pCounter self) static float GetCounterPresetImpl(pCounter self)
@ -634,7 +649,7 @@ static float GetCounterPresetImpl(pCounter self)
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
long GetCounts(pCounter self, SConnection * pCon) long GetCounts(pCounter self, SConnection * pCon)
{ {
return self->getCounts(self, pCon); return self->getCounts(self, pCon);
} }
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
static long GetCountsImpl(pCounter self, SConnection * pCon) static long GetCountsImpl(pCounter self, SConnection * pCon)
@ -643,12 +658,12 @@ static long GetCountsImpl(pCounter self, SConnection * pCon)
if (!self->isUpToDate) { if (!self->isUpToDate) {
self->pCountInt->TransferData(self, pCon); self->pCountInt->TransferData(self, pCon);
} }
return self->pDriv->lCounts[0]; return self->pDriv->lCounts[self->pDriv->iControlMonitor];
} }
/*------------------------------------------------------------------------*/ /*------------------------------------------------------------------------*/
long GetMonitor(pCounter self, int iNum, SConnection * pCon) long GetMonitor(pCounter self, int iNum, SConnection * pCon)
{ {
return self->getMonitor(self, iNum, pCon); return self->getMonitor(self, iNum, pCon);
} }
/*------------------------------------------------------------------------*/ /*------------------------------------------------------------------------*/
static long GetMonitorImpl(pCounter self, int iNum, SConnection * pCon) static long GetMonitorImpl(pCounter self, int iNum, SConnection * pCon)
@ -658,7 +673,7 @@ static long GetMonitorImpl(pCounter self, int iNum, SConnection * pCon)
if (!self->isUpToDate) { if (!self->isUpToDate) {
self->pCountInt->TransferData(self, pCon); self->pCountInt->TransferData(self, pCon);
} }
if ((iNum < 0) || (iNum > self->pDriv->iNoOfMonitors)) { if ((iNum < 0) || (iNum >= self->pDriv->iNoOfMonitors)) {
return -1L; return -1L;
} else { } else {
return self->pDriv->lCounts[iNum]; return self->pDriv->lCounts[iNum];
@ -667,7 +682,7 @@ static long GetMonitorImpl(pCounter self, int iNum, SConnection * pCon)
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
void SetMonitorValue(pCounter self, int index, long value) void SetMonitorValue(pCounter self, int index, long value)
{ {
return self->setMonitor(self, index, value); return self->setMonitor(self, index, value);
} }
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
static void SetMonitorValueImpl(pCounter self, int index, long value) static void SetMonitorValueImpl(pCounter self, int index, long value)
@ -681,7 +696,7 @@ static void SetMonitorValueImpl(pCounter self, int index, long value)
/*------------------------------------------------------------------------*/ /*------------------------------------------------------------------------*/
float GetCountTime(pCounter self, SConnection * pCon) float GetCountTime(pCounter self, SConnection * pCon)
{ {
return self->getTime(self, pCon); return self->getTime(self, pCon);
} }
/*------------------------------------------------------------------------*/ /*------------------------------------------------------------------------*/
static float GetCountTimeImpl(pCounter self, SConnection * pCon) static float GetCountTimeImpl(pCounter self, SConnection * pCon)
@ -832,6 +847,8 @@ int CountAction(SConnection * pCon, SicsInterp * pSics, void *pData,
{"getnmon", 0, {0, 0}}, {"getnmon", 0, {0, 0}},
{"state", 0, {0, 0}}, {"state", 0, {0, 0}},
{"error", 0, {0, 0}}, {"error", 0, {0, 0}},
{"getchannel",0,{0}},
{"setchannel",1,{FUPAINT}},
{"countstatus", 0, {0, 0}} {"countstatus", 0, {0, 0}}
}; };
char *pMode[] = { char *pMode[] = {
@ -849,8 +866,8 @@ int CountAction(SConnection * pCon, SicsInterp * pSics, void *pData,
argtolower(argc, argv); argtolower(argc, argv);
argx = &argv[1]; argx = &argv[1];
iRet = iRet =
EvaluateFuPa((pFuncTemplate) & ActionTemplate, 26, argc - 1, argx, EvaluateFuPa((pFuncTemplate) & ActionTemplate, 28, argc - 1, argx,
&PaRes); &PaRes);
if (iRet < 0) { if (iRet < 0) {
snprintf(pBueffel, 255,"%s", PaRes.pError); snprintf(pBueffel, 255,"%s", PaRes.pError);
SCWrite(pCon, pBueffel, eError); SCWrite(pCon, pBueffel, eError);
@ -958,7 +975,7 @@ int CountAction(SConnection * pCon, SicsInterp * pSics, void *pData,
SCSendOK(pCon); SCSendOK(pCon);
return 1; return 1;
case 11: /* status */ case 11: /* status */
case 25: case 27:
self->pCountInt->TransferData(self, pCon); self->pCountInt->TransferData(self, pCon);
if (GetCounterMode(self) == ePreset) { if (GetCounterMode(self) == ePreset) {
lVal = GetCounterPreset(self); lVal = GetCounterPreset(self);
@ -1144,8 +1161,8 @@ int CountAction(SConnection * pCon, SicsInterp * pSics, void *pData,
iRet = self->pDriv->Get(self->pDriv, PaRes.Arg[0].text, iRet = self->pDriv->Get(self->pDriv, PaRes.Arg[0].text,
PaRes.Arg[1].iVal, &fVal); PaRes.Arg[1].iVal, &fVal);
if (iRet == 1) { if (iRet == 1) {
snprintf(pBueffel,255, "%s.%s %d = %f", argv[0], PaRes.Arg[0].text, snprintf(pBueffel,255, "%s.%s %s = %f", argv[0], PaRes.Arg[0].text,
PaRes.Arg[1].iVal, fVal); PaRes.Arg[1].text, fVal);
SCWrite(pCon, pBueffel, eValue); SCWrite(pCon, pBueffel, eValue);
return 1; return 1;
} else { } else {
@ -1172,6 +1189,19 @@ int CountAction(SConnection * pCon, SicsInterp * pSics, void *pData,
SCWrite(pCon, pBueffel, eValue); SCWrite(pCon, pBueffel, eValue);
return 1; return 1;
break; break;
case 25: /* getchannel */
snprintf(pBueffel,131,"%s.getchannel = %d", argv[0], GetControlMonitor(self));
SCWrite(pCon,pBueffel,eValue);
return 1;
break;
case 26: /* setchannel */
if (SetControlMonitor(self, PaRes.Arg[0].iVal)) {
return 1;
} else {
SCWrite(pCon,"ERROR: Invalid channel id",eError);
return 0;
}
break;
default: default:
assert(0); /* internal error */ assert(0); /* internal error */
} }

View File

@ -66,6 +66,8 @@ float GetControlValue(pCounter self);
long GetCounts(pCounter self, SConnection * pCon); long GetCounts(pCounter self, SConnection * pCon);
long GetMonitor(pCounter self, int iNum, SConnection * pCon); long GetMonitor(pCounter self, int iNum, SConnection * pCon);
int GetNMonitor(pCounter self); int GetNMonitor(pCounter self);
int GetControlMonitor(pCounter self);
int SetControlMonitor(pCounter self, int channel);
void SetMonitorValue(pCounter self, int index, long value); void SetMonitorValue(pCounter self, int index, long value);
float GetCountTime(pCounter self, SConnection * pCon); float GetCountTime(pCounter self, SConnection * pCon);

View File

@ -176,11 +176,28 @@ static int SecCtrCheckStatus(void *pData, SConnection *pCon)
} }
ReleaseHdbValue(&v); ReleaseHdbValue(&v);
node = GetHipadabaNode(self->pDes->parNode,"control"); if(self->getMode(self) == eTimer){
assert(node != NULL); node = GetHipadabaNode(self->pDes->parNode,"time");
GetHipadabaPar(node,&v,pCon); assert(node != NULL);
fControl = v.v.doubleValue; GetHipadabaPar(node,&v,pCon);
fControl = v.v.doubleValue;
} else {
node = GetHipadabaNode(self->pDes->parNode,"values");
if(node != NULL) {
/*
This can be NULL if the counter is a HM. The values does not
exist and fControl is useless
The 1 below is only correct for PSI where only the first
monitor can be the control monitor. Elsewhere this must be the
control monitor channel
*/
fControl = v.v.intArray[1];
}
}
node = GetHipadabaNode(self->pDes->parNode,"preset"); node = GetHipadabaNode(self->pDes->parNode,"preset");
assert(node != NULL); assert(node != NULL);
GetHipadabaPar(node,&v,pCon); GetHipadabaPar(node,&v,pCon);

View File

@ -785,7 +785,7 @@ int DevexecAction(SConnection * pCon, SicsInterp * pSics, void *pData,
pExeList self = (pExeList) pData; pExeList self = (pExeList) pData;
if (argc < 2) { if (argc < 2) {
SCWrite(pCon, "ERROR: not enough argumentd to devexec command", SCWrite(pCon, "ERROR: not enough arguments to devexec command",
eError); eError);
return 0; return 0;
} }

View File

@ -151,9 +151,6 @@ static DevAction *DevNextAction(DevSer * devser)
} }
static void LogStart(DevSer *self) static void LogStart(DevSer *self)
{ {
if(self->startTime > 0){
printf("DEVSER: there is something fucked up in LogStart. Investigate!\n");
}
self->startTime = DoubleTime(); self->startTime = DoubleTime();
} }
static void LogResponse(DevSer *self, int error) static void LogResponse(DevSer *self, int error)

View File

@ -15,6 +15,8 @@
#include "drive.h" #include "drive.h"
#include "counter.h" #include "counter.h"
extern double DoubleTime(void);
#define DIFFMONITOR 0 #define DIFFMONITOR 0
#define SKIP 1 #define SKIP 1
@ -121,6 +123,57 @@ int DiffScanWrapper(SConnection * pCon, SicsInterp * pSics, void *pData,
return status; return status;
} }
if (strcasecmp(argv[1], "sicsvar") == 0) {
if (argc > 2) {
if (strcasecmp(argv[2], "none") == 0) {
self->sicsvar = NULL;
return 1;
} else {
self->sicsvar = FindVariable(pServ->pSics, argv[2]);
if (self->sicsvar == NULL) {
SCPrintf(pCon, eError, "Cannot find SICS Variable: %s\n", argv[2]);
return 0;
}
else if (self->sicsvar->eType != veText) {
SCPrintf(pCon, eError, "SICS Variable must be TEXT not %s\n",
self->sicsvar->eType == veInt ? "INT" :
self->sicsvar->eType == veFloat ? "FLOAT" : "unknown");
self->sicsvar = NULL;
return 0;
}
}
return 1;
} else {
SCPrintf(pCon, eValue, "sicsvar = %s\n", self->sicsvar ? self->sicsvar->name : "none");
return 1;
}
}
if (strcasecmp(argv[1], "hdbnode") == 0) {
if (argc > 2) {
if (strcasecmp(argv[2], "none") == 0) {
self->hdbnode = NULL;
return 1;
} else {
self->hdbnode = FindHdbNode(NULL, argv[2], pCon);
if (self->hdbnode == NULL) {
SCPrintf(pCon, eError, "Cannot find HDB Node: %s\n", argv[2]);
return 0;
}
else if (self->hdbnode->value.dataType != HIPTEXT) {
SCPrintf(pCon, eError, "HDB Node %s must be TEXT\n", argv[2]);
self->hdbnode = NULL;
return 0;
}
}
return 1;
} else {
char *path = NULL;
if (self->hdbnode != NULL)
path = GetHipadabaPath(self->hdbnode);
SCPrintf(pCon, eValue, "hdbnode = %s\n", path ? path : "none");
return 1;
}
}
/* /*
if we end here we are treating variables if we end here we are treating variables
*/ */
@ -180,6 +233,7 @@ static int StartDiffScan(pDiffScan self, pScanData pScan,
self->scaleMonitor = (int) ObVal(self->parArray, DIFFMONITOR); self->scaleMonitor = (int) ObVal(self->parArray, DIFFMONITOR);
self->normalizationScale = -1; self->normalizationScale = -1;
pScan->iCounts = 0; pScan->iCounts = 0;
pScan->iNP = 0;
/* /*
get variable get variable
@ -190,6 +244,7 @@ static int StartDiffScan(pDiffScan self, pScanData pScan,
SCWrite(pCon, "ERROR: cannot access scan variable", eError); SCWrite(pCon, "ERROR: cannot access scan variable", eError);
return 0; return 0;
} }
InitScanVar(pVar);
/* /*
drive to start position drive to start position
@ -250,6 +305,9 @@ static float normalizeEntry(pCountEntry pCount, pCountEntry last,
pCount->Monitors[i] = pCount->Monitors[i] =
(pCount->Monitors[i] - last->Monitors[i]) * fScale; (pCount->Monitors[i] - last->Monitors[i]) * fScale;
} }
fScale = pCount->fTime - last->fTime;
if (fScale > 0)
value /= fScale;
return value; return value;
} }
@ -271,12 +329,26 @@ static int DiffScanTask(void *pData)
char pBueffel[255]; char pBueffel[255];
long rawCount, rawMon; long rawCount, rawMon;
CountEntry rawCopy; CountEntry rawCopy;
double now;
pDiffScan self = (pDiffScan) pData; pDiffScan self = (pDiffScan) pData;
/* /*
manage skip manage skip
*/ */
#if 1
now = DoubleTime();
if (self->skip > 0) {
if (now - self->last_report_time < 0.001 * self->skip) {
return 1;
}
} else {
if (now - self->last_report_time < 0.1) {
return 1;
}
}
self->last_report_time = now;
#else
if (self->skip > 0) { if (self->skip > 0) {
if (self->skipCount > self->skip) { if (self->skipCount > self->skip) {
self->skipCount = 0; self->skipCount = 0;
@ -285,6 +357,7 @@ static int DiffScanTask(void *pData)
return 1; return 1;
} }
} }
#endif
/* /*
read motor status read motor status
@ -303,7 +376,7 @@ static int DiffScanTask(void *pData)
status = GetDrivablePosition(pVar->pObject, self->scanObject->pCon, status = GetDrivablePosition(pVar->pObject, self->scanObject->pCon,
&fPos); &fPos);
if (status == 0) { if (status == 0) {
ReleaseCountLock(pCount->pCountInt); ReleaseCountLock(pCount->pCountInt);
return finish; return finish;
} }
AppendScanVar(pVar, fPos); AppendScanVar(pVar, fPos);
@ -323,21 +396,21 @@ static int DiffScanTask(void *pData)
rawCount = data->lCount; rawCount = data->lCount;
rawMon = data->Monitors[self->scaleMonitor - 1]; rawMon = data->Monitors[self->scaleMonitor - 1];
if(rawMon > 100){ if(rawMon > 100){
self->normalizationScale = rawMon; self->normalizationScale = rawMon;
traceSys("diffscan","START:normalizing on %d, scale monitor is %d", traceSys("diffscan","START:normalizing on %d, scale monitor is %d",
self->normalizationScale, self->scaleMonitor); self->normalizationScale, self->scaleMonitor);
} else { } else {
traceSys("diffscan","START:normalization count %d, on scale monitor is %d and is to low", traceSys("diffscan","START:normalization count %ld, on scale monitor is %d and is to low",
rawMon, self->scaleMonitor); rawMon, self->scaleMonitor);
SCWrite(self->scanObject->pCon,"WARNING: Skipping first point because of low count rate", eWarning); SCWrite(self->scanObject->pCon,"WARNING: Skipping first point because of low count rate", eWarning);
return finish; return finish;
} }
} else { } else {
if (data->Monitors[self->scaleMonitor - 1] - if (data->Monitors[self->scaleMonitor - 1] -
self->last.Monitors[self->scaleMonitor - 1] < 5) { self->last.Monitors[self->scaleMonitor - 1] < 5) {
SCWrite(self->scanObject->pCon, "WARNING: low count rate", eLog); SCWrite(self->scanObject->pCon, "WARNING: low count rate", eLog);
traceSys("diffscan","RUN:low monitor difference from %d to %d",data->Monitors[self->scaleMonitor-1], traceSys("diffscan","RUN:low monitor difference from %ld to %ld",data->Monitors[self->scaleMonitor-1],
self->last.Monitors[self->scaleMonitor -1]); self->last.Monitors[self->scaleMonitor -1]);
} }
rawCount = data->lCount; rawCount = data->lCount;
rawMon = data->Monitors[self->scaleMonitor - 1]; rawMon = data->Monitors[self->scaleMonitor - 1];
@ -350,13 +423,26 @@ static int DiffScanTask(void *pData)
/* /*
print progress print progress
*/ */
snprintf(pBueffel, 255, "%5d %12.4f %12.4f RAW: %10ld %10ld", snprintf(pBueffel, 255, "%5d %12.4f %12.4f RAW: %10ld %10ld %10.3f",
self->scanObject->iCounts - 1, self->scanObject->iCounts - 1,
fPos, countValue, rawCount, rawMon); fPos, countValue, rawCount, rawMon, data->fTime);
SCWrite(self->scanObject->pCon, pBueffel, eLog); SCWrite(self->scanObject->pCon, pBueffel, eLog);
if (self->sicsvar != NULL && self->sicsvar->eType == veText)
VarSetText(self->sicsvar, pBueffel, usInternal);
if (self->hdbnode != NULL && self->hdbnode->value.dataType == HIPTEXT) {
hdbValue v;
char error[512];
cloneHdbValue(&self->hdbnode->value, &v);
if (!readHdbValue(&v, pBueffel, error, 512)) {
SCWrite(self->scanObject->pCon, error, eError);
} else {
UpdateHipadabaPar(self->hdbnode, v, self->scanObject->pCon);
}
ReleaseHdbValue(&v);
}
InvokeCallBack(self->scanObject->pCall, SCANPOINT, self->scanObject); InvokeCallBack(self->scanObject->pCall, SCANPOINT, self->scanObject);
traceSys("diffscan","RUN: pos, count, rawcount, rawmon: %f, %d, %d, %d", traceSys("diffscan","RUN: pos, count, rawcount, rawmon: %f, %f, %ld, %ld",
fPos, countValue, rawCount, rawMon); fPos, countValue, rawCount, rawMon);
/* /*
check for interrupt check for interrupt
@ -369,7 +455,7 @@ static int DiffScanTask(void *pData)
} }
if(finish == 0) { if(finish == 0) {
ReleaseCountLock(pCount->pCountInt); ReleaseCountLock(pCount->pCountInt);
} }
return finish; return finish;
@ -385,6 +471,7 @@ int RunDiffScan(pDiffScan self, pScanData pScan,
if (StartDiffScan(self, pScan, pCon, fEnd) != 1) { if (StartDiffScan(self, pScan, pCon, fEnd) != 1) {
return 0; return 0;
} }
self->last_report_time = DoubleTime();
InvokeCallBack(self->scanObject->pCall, SCANSTART, self->scanObject); InvokeCallBack(self->scanObject->pCall, SCANSTART, self->scanObject);

View File

@ -12,6 +12,9 @@
#include "obpar.h" #include "obpar.h"
#include "scan.h" #include "scan.h"
#include "scan.i" #include "scan.i"
#include "sicsvar.h"
#include "hipadaba.h"
#include "sicshipadaba.h"
typedef struct { typedef struct {
pObjectDescriptor pDes; pObjectDescriptor pDes;
@ -22,6 +25,9 @@ typedef struct {
int skip; int skip;
int skipCount; int skipCount;
pScanData scanObject; pScanData scanObject;
double last_report_time;
pSicsVariable sicsvar;
pHdb hdbnode;
} DiffScan, *pDiffScan; } DiffScan, *pDiffScan;
/*==================================================================*/ /*==================================================================*/

View File

@ -1,110 +0,0 @@
\relax
\@writefile{toc}{\contentsline {chapter}{\numberline {1}Introduction}{4}}
\@writefile{lof}{\addvspace {10\p@ }}
\@writefile{lot}{\addvspace {10\p@ }}
\@writefile{toc}{\contentsline {chapter}{\numberline {2}SICS programs, Scripts and Prerequisites}{5}}
\@writefile{lof}{\addvspace {10\p@ }}
\@writefile{lot}{\addvspace {10\p@ }}
\newlabel{f0}{{2}{5}}
\@writefile{toc}{\contentsline {section}{\numberline {2.1}Hardware}{5}}
\@writefile{toc}{\contentsline {section}{\numberline {2.2}Server programs}{5}}
\@writefile{toc}{\contentsline {chapter}{\numberline {3}General SICS Setup}{7}}
\@writefile{lof}{\addvspace {10\p@ }}
\@writefile{lot}{\addvspace {10\p@ }}
\@writefile{toc}{\contentsline {section}{\numberline {3.1}System Control}{8}}
\@writefile{toc}{\contentsline {section}{\numberline {3.2}Moving SICS}{9}}
\newlabel{f2}{{3.2}{9}}
\@writefile{toc}{\contentsline {subsection}{\numberline {3.2.1} Moving the SICS Server to a new Computer}{9}}
\@writefile{toc}{\contentsline {subsection}{\numberline {3.2.2}Exchanging the Serial Port Server}{9}}
\@writefile{toc}{\contentsline {subsection}{\numberline {3.2.3}Exchanging the Histogram Memory}{10}}
\@writefile{toc}{\contentsline {section}{\numberline {3.3}SICS Trouble Shooting }{10}}
\newlabel{f3}{{3.3}{10}}
\@writefile{toc}{\contentsline {subsection}{\numberline {3.3.1}Check Server Status}{10}}
\@writefile{toc}{\contentsline {subsection}{\numberline {3.3.2}Inspecting Log Files}{10}}
\@writefile{toc}{\contentsline {subsection}{\numberline {3.3.3}Restarting SICS}{11}}
\@writefile{toc}{\contentsline {subsection}{\numberline {3.3.4}Restart Everything}{11}}
\@writefile{toc}{\contentsline {subsection}{\numberline {3.3.5}Starting SICS Manually}{11}}
\@writefile{toc}{\contentsline {subsection}{\numberline {3.3.6}Test the SerPortServer Program}{11}}
\@writefile{toc}{\contentsline {subsection}{\numberline {3.3.7}Trouble with Environment Devices}{12}}
\@writefile{toc}{\contentsline {subsection}{\numberline {3.3.8} HELP debugging!!!!}{12}}
\@writefile{toc}{\contentsline {chapter}{\numberline {4}The SICS Initialization File}{13}}
\@writefile{lof}{\addvspace {10\p@ }}
\@writefile{lot}{\addvspace {10\p@ }}
\@writefile{toc}{\contentsline {section}{\numberline {4.1}Overview of SICS Initialization}{13}}
\newlabel{f4}{{4.1}{13}}
\@writefile{toc}{\contentsline {section}{\numberline {4.2}SICS Options and Users}{14}}
\newlabel{f5}{{4.2}{14}}
\@writefile{toc}{\contentsline {section}{\numberline {4.3}SICS Variables }{15}}
\newlabel{f6}{{4.3}{15}}
\@writefile{toc}{\contentsline {section}{\numberline {4.4}SICS Hardware Configuration}{16}}
\newlabel{f7}{{4.4}{16}}
\@writefile{toc}{\contentsline {subsection}{\numberline {4.4.1}Bus Access}{16}}
\@writefile{toc}{\contentsline {subsubsection}{Direct Access to RS232 Controllers or TCP/IP Controllers.}{16}}
\@writefile{toc}{\contentsline {subsubsection}{Accessing Serial Ports (Old System)}{17}}
\@writefile{toc}{\contentsline {subsubsection}{GPIB Controller Access}{19}}
\@writefile{toc}{\contentsline {subsection}{\numberline {4.4.2}Controllers}{20}}
\@writefile{toc}{\contentsline {subsubsection}{ECB Controllers}{20}}
\@writefile{toc}{\contentsline {subsubsection}{Siematic SPS Controllers}{21}}
\@writefile{toc}{\contentsline {subsubsection}{General Controller Object and Choppers}{22}}
\@writefile{toc}{\contentsline {subsection}{\numberline {4.4.3} Motors}{23}}
\@writefile{toc}{\contentsline {subsection}{\numberline {4.4.4}Counting Devices}{24}}
\@writefile{toc}{\contentsline {subsubsection}{Histogram Memory}{25}}
\@writefile{toc}{\contentsline {subsection}{\numberline {4.4.5}Velocity Selectors}{26}}
\@writefile{toc}{\contentsline {section}{\numberline {4.5}Initialization of General Commands}{27}}
\newlabel{f10}{{4.5}{27}}
\@writefile{toc}{\contentsline {subsection}{\numberline {4.5.1}Monochromators}{28}}
\@writefile{toc}{\contentsline {subsection}{\numberline {4.5.2}Reoccuring Tasks}{28}}
\@writefile{toc}{\contentsline {subsection}{\numberline {4.5.3}The SICS Online Help System}{29}}
\@writefile{toc}{\contentsline {subsection}{\numberline {4.5.4}Aliases in SICS}{29}}
\@writefile{toc}{\contentsline {subsubsection}{Object Aliases}{29}}
\@writefile{toc}{\contentsline {subsubsection}{Runtime Aliases}{29}}
\@writefile{toc}{\contentsline {subsubsection}{Command Aliases}{30}}
\@writefile{toc}{\contentsline {subsection}{\numberline {4.5.5}The AntiCollision Module}{30}}
\@writefile{toc}{\contentsline {section}{\numberline {4.6}The Internal Scan Commands}{31}}
\newlabel{f11}{{4.6}{31}}
\@writefile{toc}{\contentsline {subsection}{\numberline {4.6.1}Scan Concepts}{31}}
\@writefile{toc}{\contentsline {subsection}{\numberline {4.6.2}User Definable Scan Functions}{34}}
\@writefile{toc}{\contentsline {subsection}{\numberline {4.6.3}User Defined Scans(Old Style)}{35}}
\@writefile{toc}{\contentsline {subsection}{\numberline {4.6.4}The Scan Command Header Description File}{35}}
\@writefile{toc}{\contentsline {subsection}{\numberline {4.6.5}Differential Scans}{36}}
\@writefile{toc}{\contentsline {subsection}{\numberline {4.6.6}Peak Analysis}{37}}
\@writefile{toc}{\contentsline {subsection}{\numberline {4.6.7}Common Scan Scripts}{37}}
\@writefile{toc}{\contentsline {section}{\numberline {4.7}Scripting NeXus Files}{37}}
\newlabel{f12}{{4.7}{37}}
\@writefile{toc}{\contentsline {subsection}{\numberline {4.7.1}Usage}{38}}
\@writefile{toc}{\contentsline {subsubsection}{File Opening and Closing}{38}}
\@writefile{toc}{\contentsline {subsubsection}{Writing Things}{38}}
\@writefile{toc}{\contentsline {section}{\numberline {4.8}Automatic Updating of NeXus Files}{39}}
\@writefile{toc}{\contentsline {subsection}{\numberline {4.8.1}Prerequisites for Using the Automatic Update Manager}{39}}
\@writefile{toc}{\contentsline {subsection}{\numberline {4.8.2}Installing Automatic Update}{40}}
\@writefile{toc}{\contentsline {subsection}{\numberline {4.8.3}Configuring Automatic Update}{40}}
\@writefile{toc}{\contentsline {section}{\numberline {4.9}Instrument Specific SICS Initializations}{40}}
\@writefile{toc}{\contentsline {subsection}{\numberline {4.9.1}Initialization for Four Circle Diffractometers}{40}}
\newlabel{f13}{{4.9.1}{40}}
\@writefile{toc}{\contentsline {subsection}{\numberline {4.9.2}Triple Axis Spectrometer Specific Commands}{42}}
\newlabel{f14}{{4.9.2}{42}}
\@writefile{toc}{\contentsline {subsection}{\numberline {4.9.3}Special Commands for the Reflectometer (AMOR)}{42}}
\newlabel{f15}{{4.9.3}{42}}
\@writefile{toc}{\contentsline {subsubsection}{AMOR Status Display Commands}{43}}
\@writefile{toc}{\contentsline {subsection}{\numberline {4.9.4}SANS Special Commands}{44}}
\newlabel{f16}{{4.9.4}{44}}
\@writefile{toc}{\contentsline {subsection}{\numberline {4.9.5}Special FOCUS Initializations}{45}}
\newlabel{f17}{{4.9.5}{45}}
\@writefile{toc}{\contentsline {subsubsection}{Special Internal FOCUS Support Commands}{45}}
\@writefile{toc}{\contentsline {chapter}{\numberline {5}Programming SICS Macros}{46}}
\@writefile{lof}{\addvspace {10\p@ }}
\@writefile{lot}{\addvspace {10\p@ }}
\newlabel{f18}{{5}{46}}
\@writefile{toc}{\contentsline {section}{\numberline {5.1}Input/Output}{46}}
\@writefile{toc}{\contentsline {section}{\numberline {5.2}Error Handling}{47}}
\@writefile{toc}{\contentsline {section}{\numberline {5.3}Interacting with SICS within a Script}{47}}
\@writefile{toc}{\contentsline {section}{\numberline {5.4}SICS Interfaces in Tcl}{47}}
\@writefile{toc}{\contentsline {subsection}{\numberline {5.4.1}The Object Interface}{47}}
\@writefile{toc}{\contentsline {subsection}{\numberline {5.4.2}Overriding the Drivable Interface with Tcl}{48}}
\@writefile{toc}{\contentsline {chapter}{\numberline {6}The McStas SICS Interface}{49}}
\@writefile{lof}{\addvspace {10\p@ }}
\@writefile{lot}{\addvspace {10\p@ }}
\newlabel{f8}{{6}{49}}
\@writefile{toc}{\contentsline {section}{\numberline {6.1}McStas Requirements and SICS Requirements}{50}}
\@writefile{toc}{\contentsline {section}{\numberline {6.2}The McStas Reader}{50}}
\@writefile{toc}{\contentsline {section}{\numberline {6.3}The McStas Controller}{51}}

Binary file not shown.

View File

@ -1 +0,0 @@
\relax

View File

@ -226,7 +226,7 @@ A valid SICS object structure has to look like this:
Please note that the first item in the data structure MUST be a Please note that the first item in the data structure MUST be a
pointer to an SICS object descriptor. Add your own stuff below pointer to an SICS object descriptor. Add your own stuff below
that. If you do not adhere to this requirement, SICS will dump core on that. If you do not adhere to this requirement, SICS will dump core on
you rather sooner then later. you rather sooner than later.
SICS needs this object descriptor for its own internal purposes. The SICS needs this object descriptor for its own internal purposes. The
@ -566,7 +566,7 @@ This code also shows the necessary error checking. It also shows how
to check for possible interrupts after such an operation. It is very to check for possible interrupts after such an operation. It is very
advisable to do this because the user may have interrupted the advisable to do this because the user may have interrupted the
process. And she might not be all to happy if the new command just process. And she might not be all to happy if the new command just
continues with the next step rather then aborting the process. continues with the next step rather than aborting the process.
\section{SICS Interfaces}\label{interface}\label{inter} \section{SICS Interfaces}\label{interface}\label{inter}

View File

@ -8,7 +8,7 @@ subdivided into a driver and the logical object.
There is a problem here. There are some data fields and functions There is a problem here. There are some data fields and functions
which must be present for any motor driver. Then there are fields which must be present for any motor driver. Then there are fields
which are specific just to a special implementation of a mot which are specific just to a special implementation of a mot
driver. There are several ways to deal with this. The way choosen for driver. There are several ways to deal with this. The way chosen for
the motor driver is a kind of overlay. The first few fields of a valid the motor driver is a kind of overlay. The first few fields of a valid
motor driver structure MUST be specified in the same order as given motor driver structure MUST be specified in the same order as given
below. A special motor driver can add additional fields at the end of below. A special motor driver can add additional fields at the end of
@ -122,12 +122,12 @@ creates a simulation motor driver.
\end{description} \end{description}
\subsubsection{The Motor Logical Object} \subsubsection{The Motor Logical Object}
The motor object represents the motor to SICS. One of its responsabilities The motor object represents the motor to SICS. One of its responsibilities
is to drive motor operations and error checking. The scheme is to drive motor operations and error checking. The scheme
implemented is that the motor object tries to bring the motor to its implemented is that the motor object tries to bring the motor to its
position at least three times before a failure is recorded. Also the position at least three times before a failure is recorded. Also the
motor object keeps track of a count of failed operations. If this motor object keeps track of a count of failed operations. If this
count gets to high an interrupt is issued to stop the instrument. This count gets too high an interrupt is issued to stop the instrument. This
was put in after Druechal tried to drive over a slab of concrete for a was put in after Druechal tried to drive over a slab of concrete for a
whole night and subsequently broke a clutch. whole night and subsequently broke a clutch.
Motors are represented by the Motors are represented by the
@ -164,7 +164,7 @@ object.
Much of the action of the motor is hidden in the implementation of the Much of the action of the motor is hidden in the implementation of the
drivable interface to the motor. Additionally the functions as given below drivable interface to the motor. Additionally the functions as given below
are defined. All functions take a pointer to the motor object data structure are defined. All functions take a pointer to the motor object data structure
as a parameter. They retun 0 on success or 1 on failure while not stated as a parameter. They return 0 on success or 1 on failure while not stated
otherwise. otherwise.
\begin{description} \begin{description}
\item[int MotorGetPar(pMotor self, char *name, float *fVal)] retrieves the \item[int MotorGetPar(pMotor self, char *name, float *fVal)] retrieves the

View File

@ -1,47 +1,47 @@
<html> <html>
<head> <head>
<title>HRPT motor list</title> <title>HRPT motor list</title>
</head> </head>
<body> <body>
<H2>HRPT motor list</H2> <H2>HRPT motor list</H2>
<P> <P>
<DL> <DL>
<DT>CEX1 <DT>CEX1
<DD>inner collimator drum <DD>inner collimator drum
<DT>CEX2 <DT>CEX2
<DD>outer collimator drum <DD>outer collimator drum
<DT>MOMU, A1 <DT>MOMU, A1
<DD>omega rotation of upper monochromator crystal. <DD>omega rotation of upper monochromator crystal.
<DT>MTVU, A12 <DT>MTVU, A12
<DD>translation vertical to the upper crystal. <DD>translation vertical to the upper crystal.
<DT>MTPU, A13 <DT>MTPU, A13
<DD>translation paralell to the upper crystal <DD>translation paralell to the upper crystal
<DT>MGVU, A14 <DT>MGVU, A14
<DD>tilt goniometer vertical to upper crystal. <DD>tilt goniometer vertical to upper crystal.
<DT>MGPU, A15 <DT>MGPU, A15
<DD>tilt goniometer paralell to upper crystal. <DD>tilt goniometer paralell to upper crystal.
<DT>MCVU, A16 <DT>MCVU, A16
<dd>vertical curvature of upper crystal. <dd>vertical curvature of upper crystal.
<DT>MOML, B1 <DT>MOML, B1
<DD>omega rotation of lower monochromator crystal. <DD>omega rotation of lower monochromator crystal.
<DT>MTVL, A22 <DT>MTVL, A22
<DD>translation vertical to the lower crystal. <DD>translation vertical to the lower crystal.
<DT>MTPL, A23 <DT>MTPL, A23
<DD>translation paralell to the lower crystal <DD>translation paralell to the lower crystal
<DT>MGVL, A24 <DT>MGVL, A24
<DD>tilt goniometer vertical to lower crystal. <DD>tilt goniometer vertical to lower crystal.
<DT>MGPL, A25 <DT>MGPL, A25
<DD>tilt goniometer paralell to lower crystal. <DD>tilt goniometer paralell to lower crystal.
<DT>MCVL, A26 <DT>MCVL, A26
<dd>vertical curvature of lower crystal. <dd>vertical curvature of lower crystal.
<dT>MEXZ, A37 <dT>MEXZ, A37
<DD>lift <DD>lift
<DT>Table, A3 <DT>Table, A3
<DD>Sample rotation. <DD>Sample rotation.
<DT>TwoThetaD, A4 <DT>TwoThetaD, A4
<DD>Two Theta detector. <DD>Two Theta detector.
</DL> </DL>
</p> </p>
</body> </body>
</html> </html>

14
drive.c
View File

@ -1,7 +1,7 @@
/*-------------------------------------------------------------------------- /*--------------------------------------------------------------------------
Implementation file for the drive command Implementation file for the drive command
This version as Test for Device Executor. This version as Test for Device Executor.
Mark Koennecke, December 1996 Mark Koennecke, December 1996
@ -39,6 +39,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <assert.h> #include <assert.h>
#include <string.h> #include <string.h>
#include <math.h>
#include "fortify.h" #include "fortify.h"
#include "sics.h" #include "sics.h"
#include "drive.h" #include "drive.h"
@ -66,7 +67,7 @@ int Drive(SConnection * pCon, SicsInterp * pInter, char *name, float fNew)
/* check if user is allowed to drive */ /* check if user is allowed to drive */
if (!SCMatchRights(pCon, usUser)) { if (!SCMatchRights(pCon, usUser)) {
snprintf(pBueffel, 511, "Insuficient Privilege to drive %s", name); snprintf(pBueffel, 511, "Insufficient Privilege to drive %s", name);
SCWrite(pCon, pBueffel, eError); SCWrite(pCon, pBueffel, eError);
return 0; return 0;
} }
@ -301,7 +302,7 @@ int DriveWrapper(SConnection * pCon, SicsInterp * pSics, void *pData,
return 0; return 0;
} }
/* interprete arguments as pairs name value and try to start */ /* interpret arguments as pairs (name, value) and check */
for (i = 1; i < argc; i += 2) { for (i = 1; i < argc; i += 2) {
if (argv[i + 1] == NULL) { if (argv[i + 1] == NULL) {
snprintf(pBueffel, 511, "ERROR: no value found for driving %s", argv[i]); snprintf(pBueffel, 511, "ERROR: no value found for driving %s", argv[i]);
@ -311,7 +312,12 @@ int DriveWrapper(SConnection * pCon, SicsInterp * pSics, void *pData,
iRet = Tcl_GetDouble(tcl_interp, argv[i + 1], &dTarget); iRet = Tcl_GetDouble(tcl_interp, argv[i + 1], &dTarget);
if (iRet == TCL_ERROR) { if (iRet == TCL_ERROR) {
SCWrite(pCon, Tcl_GetStringResult(tcl_interp), eError); SCWrite(pCon, Tcl_GetStringResult(tcl_interp), eError);
StopExe(GetExecutor(), "ALL"); return 0;
} else if (!isfinite(dTarget)) {
snprintf(pBueffel, 511,
"ERROR: target %s value for %s is not a finite number",
argv[i + 1], argv[i]);
SCWrite(pCon, pBueffel, eError);
return 0; return 0;
} }
iRet = Start2Run(pCon, pSics, argv[i], RUNDRIVE, dTarget); iRet = Start2Run(pCon, pSics, argv[i], RUNDRIVE, dTarget);

View File

@ -101,6 +101,7 @@ void DeleteDynString(pDynString self)
if (self->pBuffer) if (self->pBuffer)
free(self->pBuffer); free(self->pBuffer);
self->iMAGIC = 0;
free(self); free(self);
} }

View File

@ -35,7 +35,14 @@ typedef struct {
* \return the new error message list head * \return the new error message list head
*/ */
void ErrPutMsg(ErrList *list, char *fmt, ...); #if __GNUC__ > 2
#define G_GNUC_PRINTF( format_idx, arg_idx ) \
__attribute__((__format__ (__printf__, format_idx, arg_idx)))
#else
#define G_GNUC_PRINTF( format_idx, arg_idx )
#endif
void ErrPutMsg(ErrList *list, char *fmt, ...) G_GNUC_PRINTF (2, 3);
#undef G_GNUC_PRINTF
/** \brief Get the most recent error message /** \brief Get the most recent error message
* \param list the error list * \param list the error list

View File

@ -178,7 +178,7 @@ static pDynString findBlockEnd(pExeBuf self)
{ {
pDynString command = NULL; pDynString command = NULL;
char *buffer = NULL; char *buffer = NULL;
int i; int i, j;
assert(self); assert(self);
@ -190,7 +190,8 @@ static pDynString findBlockEnd(pExeBuf self)
if (self->end != -1) { if (self->end != -1) {
self->start = self->end + 1; self->start = self->end + 1;
} }
for (i = self->start; i < strlen(buffer); i++) { j = strlen(buffer);
for (i = self->start; i < j; i++) {
DynStringConcatChar(command, buffer[i]); DynStringConcatChar(command, buffer[i]);
if (buffer[i] == '\n') { if (buffer[i] == '\n') {
self->lineno++; self->lineno++;

View File

@ -1,409 +1,409 @@
Fortify - fortified memory allocation shell for C and C++ Fortify - fortified memory allocation shell for C and C++
--------------------------------------------------------- ---------------------------------------------------------
written by Simon P. Bullen written by Simon P. Bullen
Cybergraphic Cybergraphic
Release 1.0, 2/2/1995 Release 1.0, 2/2/1995
This software is not public domain. All material in This software is not public domain. All material in
this archive is <20> Copyright 1995 Simon P. Bullen. The this archive is <20> Copyright 1995 Simon P. Bullen. The
software is freely distrubtable, with the condition that no software is freely distrubtable, with the condition that no
more than a nominal fee is charged for media. Everything in more than a nominal fee is charged for media. Everything in
this distrubution must be kept together, in original, this distrubution must be kept together, in original,
unmodified form. unmodified form.
The files may be modified for your own personal use, but The files may be modified for your own personal use, but
modified files may not be distributed. modified files may not be distributed.
The material is provided "as is" without warranty of any The material is provided "as is" without warranty of any
kind. The author accepts no responsibilty for damage caused kind. The author accepts no responsibilty for damage caused
by this software. by this software.
email: sbullen@ozemail.com.au email: sbullen@ozemail.com.au
snail: Simon P. Bullen snail: Simon P. Bullen
PO BOX 12138 PO BOX 12138
A'Beckett St A'Beckett St
Melbourne 3000 Melbourne 3000
Australia Australia
CONTENTS CONTENTS
-------- --------
Your archive should have the following files: Your archive should have the following files:
file_id.diz file_id.diz
fortify.c fortify.c
fortify.doc fortify.doc
fortify.h fortify.h
read.me read.me
test.c test.c
ufortify.h ufortify.h
ufortify.hpp ufortify.hpp
zfortify.cpp zfortify.cpp
zfortify.hpp zfortify.hpp
ztest.cpp ztest.cpp
OVERVIEW OVERVIEW
-------- --------
Fortify is a descendant of a library I wrote way back in 1990 called Fortify is a descendant of a library I wrote way back in 1990 called
SafeMem. It is a (fortified) shell for memory allocations. It works with SafeMem. It is a (fortified) shell for memory allocations. It works with
the malloc/free family of functions, as well as new/delete in C++. It can the malloc/free family of functions, as well as new/delete in C++. It can
be adapted to most memory management functions; the original version of be adapted to most memory management functions; the original version of
SafeMem worked only with the Amiga's AllocMem/FreeMem. I haven't been SafeMem worked only with the Amiga's AllocMem/FreeMem. I haven't been
writing much Amiga specific software lately, so the Amiga version of writing much Amiga specific software lately, so the Amiga version of
Fortify is way out of date, hence it's absense from this archive. Fortify is way out of date, hence it's absense from this archive.
Fortify is designed to detect bad things happening, or at the very Fortify is designed to detect bad things happening, or at the very
least encourage intermittent problems to occur all the time. It is capable least encourage intermittent problems to occur all the time. It is capable
of detecting memory leaks, writes beyond and before memory blocks, and of detecting memory leaks, writes beyond and before memory blocks, and
breaks software that relies on the state of uninitialized memory, and breaks software that relies on the state of uninitialized memory, and
software that uses memory after it's been freed. software that uses memory after it's been freed.
It works by allocating extra space on each block. This includes a It works by allocating extra space on each block. This includes a
private header (which is used to keep track of Fortify's list of allocated private header (which is used to keep track of Fortify's list of allocated
memory), and two "fortification" zones or sentinals (which are used to memory), and two "fortification" zones or sentinals (which are used to
detect writing outside the bound of the user's memory). detect writing outside the bound of the user's memory).
Fortify VERSUS ZFortify Fortify VERSUS ZFortify
----------------------- -----------------------
Fortify provides fortification for malloc/realloc/free, and ZFortify Fortify provides fortification for malloc/realloc/free, and ZFortify
provides fortifications for new/delete. It is possible to use both provides fortifications for new/delete. It is possible to use both
versions in the one program, if you are mixing C and C++. Just make sure versions in the one program, if you are mixing C and C++. Just make sure
(as you already should be) that you never free() memory you new'd, and (as you already should be) that you never free() memory you new'd, and
other such illegal mismatching. other such illegal mismatching.
(Why _Z_ fortify? It's a long story...) (Why _Z_ fortify? It's a long story...)
Fortify INSTALLATION (C) Fortify INSTALLATION (C)
------------------------ ------------------------
To use Fortify, each source file will need to #include "fortify.h". To To use Fortify, each source file will need to #include "fortify.h". To
enable Fortify, define the symbol FORTIFY. If FORTIFY is not defined, it enable Fortify, define the symbol FORTIFY. If FORTIFY is not defined, it
will compile away to nothing. If you do not have stdout available, you may will compile away to nothing. If you do not have stdout available, you may
wish to set an alternate output function. See Fortify_SetOutputFunc(), wish to set an alternate output function. See Fortify_SetOutputFunc(),
below. below.
You will also need to link in fortify.o You will also need to link in fortify.o
ZFortify INSTALLATION (C++) ZFortify INSTALLATION (C++)
--------------------------- ---------------------------
The minimum you need to do for ZFortify is to define the symbol The minimum you need to do for ZFortify is to define the symbol
ZFORTIFY, and link zfortify.o. Each source file should also include ZFORTIFY, and link zfortify.o. Each source file should also include
"zfortify.hpp", but this isn't strictly necessary. If a file doesn't "zfortify.hpp", but this isn't strictly necessary. If a file doesn't
#include "Fortify.hpp", then it's allocations will still be fortified, #include "Fortify.hpp", then it's allocations will still be fortified,
however you will not have any source-code details in any of the output however you will not have any source-code details in any of the output
messages (this will be the case for all libraries, etc, unless you have the messages (this will be the case for all libraries, etc, unless you have the
source for the library and can recompile it with Fortify). source for the library and can recompile it with Fortify).
If you do not have stdout available, you may wish to set an alternate If you do not have stdout available, you may wish to set an alternate
output function, or turn on the AUTOMATIC_LOGFILE. See output function, or turn on the AUTOMATIC_LOGFILE. See
ZFortify_SetOutputFunc() and AUTOMATIC_LOGFILE, below. ZFortify_SetOutputFunc() and AUTOMATIC_LOGFILE, below.
COMPILE TIME CUSTOMIZATIONS COMPILE TIME CUSTOMIZATIONS
--------------------------- ---------------------------
The files "ufortify.h" and "ufortify.hpp" contain a number of #defines The files "ufortify.h" and "ufortify.hpp" contain a number of #defines
that you can use to customize Fortify's behavior. that you can use to customize Fortify's behavior.
#define ZFORTIFY_PROVIDE_ARRAY_NEW #define ZFORTIFY_PROVIDE_ARRAY_NEW
Some C++ compilers have a separate operator for newing arrays. If your Some C++ compilers have a separate operator for newing arrays. If your
compiler does, you will need to define this symbol. If you are unsure, compiler does, you will need to define this symbol. If you are unsure,
dont worry about it too much, your program won't compile or link without dont worry about it too much, your program won't compile or link without
the correct setting. GCC 2.6.3 and Borland C++ 4.5 both need this symbol. the correct setting. GCC 2.6.3 and Borland C++ 4.5 both need this symbol.
Microsoft C++ 1.5 and SAS 6.5 C++ both dont. Microsoft C++ 1.5 and SAS 6.5 C++ both dont.
#define FORTIFY_STORAGE #define FORTIFY_STORAGE
#define ZFORTIFY_STORAGE #define ZFORTIFY_STORAGE
You can use this to apply a storage type to all of Fortify's exportable You can use this to apply a storage type to all of Fortify's exportable
functions. If you are putting Fortify in an export library for example, functions. If you are putting Fortify in an export library for example,
you may need to put __export here, or some such rubbish. you may need to put __export here, or some such rubbish.
#define FORTIFY_BEFORE_SIZE 32 #define FORTIFY_BEFORE_SIZE 32
#define FORTIFY_BEFORE_VALUE 0xA3 #define FORTIFY_BEFORE_VALUE 0xA3
#define FORTIFY_AFTER_SIZE 32 #define FORTIFY_AFTER_SIZE 32
#define FORTIFY_AFTER_VALUE 0xA5 #define FORTIFY_AFTER_VALUE 0xA5
#define ZFORTIFY_BEFORE_SIZE 32 #define ZFORTIFY_BEFORE_SIZE 32
#define ZFORTIFY_BEFORE_VALUE 0xA3 #define ZFORTIFY_BEFORE_VALUE 0xA3
#define ZFORTIFY_AFTER_SIZE 32 #define ZFORTIFY_AFTER_SIZE 32
#define ZFORTIFY_AFTER_VALUE 0xA5 #define ZFORTIFY_AFTER_VALUE 0xA5
These values define how much "fortification" is placed around each These values define how much "fortification" is placed around each
memory block you allocate. Fortify will place _BEFORE_SIZE bytes worth of memory block you allocate. Fortify will place _BEFORE_SIZE bytes worth of
memory right before your allocation block, and _AFTER_SIZE bytes worth memory right before your allocation block, and _AFTER_SIZE bytes worth
after your allocation block, and these will be initialized to _BEFORE_VALUE after your allocation block, and these will be initialized to _BEFORE_VALUE
and _AFTER_VALUE respectively. If your program then accidentally writes and _AFTER_VALUE respectively. If your program then accidentally writes
too far beyond the end of the block, for example, Fortify will be able to too far beyond the end of the block, for example, Fortify will be able to
detect this (so long as you didn't happen to write in _AFTER_VALUE!). detect this (so long as you didn't happen to write in _AFTER_VALUE!).
If you don't want these fortifications to be allocated, specify a If you don't want these fortifications to be allocated, specify a
_SIZE of 0. Note that the _VALUE parameters are 8 bits. _SIZE of 0. Note that the _VALUE parameters are 8 bits.
#define FILL_ON_MALLOC #define FILL_ON_MALLOC
#define FILL_ON_MALLOC_VALUE 0xA7 #define FILL_ON_MALLOC_VALUE 0xA7
#define FILL_ON_NEW #define FILL_ON_NEW
#define FILL_ON_NEW_VALUE 0xA7 #define FILL_ON_NEW_VALUE 0xA7
Programs often rely on uninitialized memory being certain values Programs often rely on uninitialized memory being certain values
(usually 0). If you define FILL_ON_NEW, all memory that you new will be (usually 0). If you define FILL_ON_NEW, all memory that you new will be
initialized to FILL_ON_NEW_VALUE, which you should define to be some horrid initialized to FILL_ON_NEW_VALUE, which you should define to be some horrid
value (definately NOT 0). This will encourage all code that relies on value (definately NOT 0). This will encourage all code that relies on
uninitialized memory to behave rather differently when Fortify is running. uninitialized memory to behave rather differently when Fortify is running.
#define FILL_ON_FREE #define FILL_ON_FREE
#define FILL_ON_FREE_VALUE 0xA9 #define FILL_ON_FREE_VALUE 0xA9
#define FILL_ON_DELETE #define FILL_ON_DELETE
#define FILL_ON_DELETE_VALUE 0xA9 #define FILL_ON_DELETE_VALUE 0xA9
Programmers often try to use memory after they've freed it, which can Programmers often try to use memory after they've freed it, which can
sometimes work (so long as noboby else has modified the memory before you sometimes work (so long as noboby else has modified the memory before you
look at it), but is incredibly dangerous and definately bad practice. If look at it), but is incredibly dangerous and definately bad practice. If
FILL_ON_DELETE is defined, all memory you free will be stomped out with FILL_ON_DELETE is defined, all memory you free will be stomped out with
FILL_ON_DELETE_VALUE, which ensures that any attempt to read freed memory FILL_ON_DELETE_VALUE, which ensures that any attempt to read freed memory
will give incorrect results. will give incorrect results.
#define CHECK_ALL_MEMORY_ON_MALLOC #define CHECK_ALL_MEMORY_ON_MALLOC
#define CHECK_ALL_MEMORY_ON_FREE #define CHECK_ALL_MEMORY_ON_FREE
#define CHECK_ALL_MEMORY_ON_NEW #define CHECK_ALL_MEMORY_ON_NEW
#define CHECK_ALL_MEMORY_ON_DELETE #define CHECK_ALL_MEMORY_ON_DELETE
CHECK_ALL_MEMORY_ON... means that for every single memory allocation CHECK_ALL_MEMORY_ON... means that for every single memory allocation
or deallocation, every single block of memory will be checked. This can or deallocation, every single block of memory will be checked. This can
considerably slow down programs if you have a large number of blocks considerably slow down programs if you have a large number of blocks
allocated. You would normally only need to turn this on if you are trying allocated. You would normally only need to turn this on if you are trying
to pinpoint where a corruption was occurring. to pinpoint where a corruption was occurring.
A block of memory is always checked when it is freed, so if A block of memory is always checked when it is freed, so if
CHECK_ALL... isn't turned on, corruptions will still be detected CHECK_ALL... isn't turned on, corruptions will still be detected
eventually. eventually.
You can also force Fortify to check all memory with a call to You can also force Fortify to check all memory with a call to
Fortify_CheckAllMemory(). If you have a memory corruption you can't find, Fortify_CheckAllMemory(). If you have a memory corruption you can't find,
sprinkling these through the suspect code will help narrow it down. sprinkling these through the suspect code will help narrow it down.
#define PARANOID_FREE #define PARANOID_FREE
#define PARANOID_DELETE #define PARANOID_DELETE
PARANOID_... - This means that zFortify traverses the memory list to PARANOID_... - This means that zFortify traverses the memory list to
ensure the memory you are about to free was really allocated by it. You ensure the memory you are about to free was really allocated by it. You
probably only need this in extreme circumstances. Not having this defined probably only need this in extreme circumstances. Not having this defined
will still trap attempts to free memory that wasn't allocated, unless will still trap attempts to free memory that wasn't allocated, unless
someone is deliberately trying to fool zFortify. someone is deliberately trying to fool zFortify.
Paranoid mode adds considerable overhead to freeing memory, especially Paranoid mode adds considerable overhead to freeing memory, especially
if you are freeing things in the same order you allocated them (Paranoid if you are freeing things in the same order you allocated them (Paranoid
mode is most efficient if you are freeing things in the reverse order they mode is most efficient if you are freeing things in the reverse order they
were allocated). were allocated).
#define WARN_ON_MALLOC_FAIL #define WARN_ON_MALLOC_FAIL
#define WARN_ON_ZERO_MALLOC #define WARN_ON_ZERO_MALLOC
#define WARN_ON_FALSE_FAIL #define WARN_ON_FALSE_FAIL
#define WARN_ON_UNSIGNED_LONG_OVERFLOW #define WARN_ON_UNSIGNED_LONG_OVERFLOW
#define WARN_ON_NEW_FAIL #define WARN_ON_NEW_FAIL
#define WARN_ON_ZERO_NEW #define WARN_ON_ZERO_NEW
These defines enable the output of warning that aren't strictly errors, These defines enable the output of warning that aren't strictly errors,
but can be useful to determine what lead to a program crashing. but can be useful to determine what lead to a program crashing.
WARN_ON_NEW_FAIL causes a debug to be issued whenever new fails. WARN_ON_NEW_FAIL causes a debug to be issued whenever new fails.
WARN_ON_ZERO_NEW causes a debug to be issued whenever a new of a zero WARN_ON_ZERO_NEW causes a debug to be issued whenever a new of a zero
byte object is attempted. This is fairly unlikely in C++, and is much more byte object is attempted. This is fairly unlikely in C++, and is much more
likely when using malloc(). likely when using malloc().
WARN_ON_FALSE_FAIL causes a debug to be issued when a new is "false" WARN_ON_FALSE_FAIL causes a debug to be issued when a new is "false"
failed. ZSee Fortify_SetNewFailRate() for more information. failed. ZSee Fortify_SetNewFailRate() for more information.
WARN_ON_UNSIGNED_LONG_OVERFLOW causes Fortify to check for breaking the WARN_ON_UNSIGNED_LONG_OVERFLOW causes Fortify to check for breaking the
32 bit limit. This was more of a problem in 16-bit applications where 32 bit limit. This was more of a problem in 16-bit applications where
breaking the 16 bit limit was much more likely. The problem is that breaking the 16 bit limit was much more likely. The problem is that
Fortify adds a small amount of overhead to a memory block; so in a 16-bit Fortify adds a small amount of overhead to a memory block; so in a 16-bit
size_t environment, if you tried to allocate 64K, Fortify would make that size_t environment, if you tried to allocate 64K, Fortify would make that
block bigger than 64K and your allocation would fail due to the presence of block bigger than 64K and your allocation would fail due to the presence of
Fortify. With size_t being 32 bits for all environments worth programming Fortify. With size_t being 32 bits for all environments worth programming
in, this problem is extremely unlikely (Unless you plan to allocate 4 in, this problem is extremely unlikely (Unless you plan to allocate 4
gigabytes). gigabytes).
#define AUTOMATIC_LOG_FILE #define AUTOMATIC_LOG_FILE
#define LOG_FILENAME "fortify.log" #define LOG_FILENAME "fortify.log"
#define FIRST_ERROR_FUNCTION #define FIRST_ERROR_FUNCTION
If AUTOMATIC_LOG_FILE is defined (C++ version /ZFortify only), then If AUTOMATIC_LOG_FILE is defined (C++ version /ZFortify only), then
Fortify will be automatically started for you, Fortify messages sent to the Fortify will be automatically started for you, Fortify messages sent to the
named log file, and a list of unfreed memory dumped on termination (where named log file, and a list of unfreed memory dumped on termination (where
the log file will be automatically closed for you. If no Fortify was the log file will be automatically closed for you. If no Fortify was
output, the log file will not be altered. There are timestamps in the log output, the log file will not be altered. There are timestamps in the log
file to ensure you're reading the correct messages. file to ensure you're reading the correct messages.
FIRST_ERROR_FUNCTION will be called upon generation of the first FIRST_ERROR_FUNCTION will be called upon generation of the first
Fortify message, so that the user can tell a Fortify report has been Fortify message, so that the user can tell a Fortify report has been
generated. Otherwise, Fortify would quietly write all this useful stuff generated. Otherwise, Fortify would quietly write all this useful stuff
out to the log file, and no-one would know to look there! out to the log file, and no-one would know to look there!
#define FORTIFY_LOCK() #define FORTIFY_LOCK()
#define FORTIFY_UNLOCK() #define FORTIFY_UNLOCK()
#define ZFORTIFY_LOCK() #define ZFORTIFY_LOCK()
#define ZFORTIFY_UNLOCK() #define ZFORTIFY_UNLOCK()
In a multi-threaded environment, we need to arbitrate access to the In a multi-threaded environment, we need to arbitrate access to the
foritfy memory list. This is what ZFORTIFY_LOCK() and ZFORTIFY_UNLOCK() foritfy memory list. This is what ZFORTIFY_LOCK() and ZFORTIFY_UNLOCK()
are used for. The calls to ZFORTIFY_LOCK() and ZFORTIFY_UNLOCK() must are used for. The calls to ZFORTIFY_LOCK() and ZFORTIFY_UNLOCK() must
nest. If no two threads/tasks/processes will be using the same Fortify at nest. If no two threads/tasks/processes will be using the same Fortify at
the same time, then ZFORTIFY_LOCK() and ZFORTIFY_UNLOCK() can safely be the same time, then ZFORTIFY_LOCK() and ZFORTIFY_UNLOCK() can safely be
#defined away to nothing. #defined away to nothing.
RUN TIME CONTROL RUN TIME CONTROL
---------------- ----------------
Fortify can also be controlled at run time with a few special Fortify can also be controlled at run time with a few special
functions, which compile away to nothing if FORTIFY isn't defined, and do functions, which compile away to nothing if FORTIFY isn't defined, and do
nothing if Fortify has been disabled with Fortify_Disable(). These nothing if Fortify has been disabled with Fortify_Disable(). These
functions all apply to ZFortify as well (The ZFortify versions have a functions all apply to ZFortify as well (The ZFortify versions have a
ZFortify_ prefix, of course). ZFortify_ prefix, of course).
Fortify_Disable() - This function provides a mechanism to disable Fortify_Disable() - This function provides a mechanism to disable
Fortify without recompiling all the sourcecode. It can only be called, Fortify without recompiling all the sourcecode. It can only be called,
though, when there is no memory on the Fortify list. (Ideally, at the though, when there is no memory on the Fortify list. (Ideally, at the
start of the program before any memory has been allocated). If you call start of the program before any memory has been allocated). If you call
this function when there IS memory on the Fortify list, it will issue an this function when there IS memory on the Fortify list, it will issue an
error, and Fortify will not be disabled. error, and Fortify will not be disabled.
Fortify_SetOutputFunc(Fortify_OutputFuncPtr Output) - Sets the function Fortify_SetOutputFunc(Fortify_OutputFuncPtr Output) - Sets the function
used to output all error and diagnostic messages by Fortify. The output used to output all error and diagnostic messages by Fortify. The output
function takes a single (const char *) argument, and must be able to handle function takes a single (const char *) argument, and must be able to handle
newlines. The function returns the old pointer. newlines. The function returns the old pointer.
The default output func is a printf() to stdout. Unless you are using The default output func is a printf() to stdout. Unless you are using
AUTOMATIC_LOG_FILE, where the default is to output to the log file. AUTOMATIC_LOG_FILE, where the default is to output to the log file.
Fortify_SetNewFailRate(int Percent) - Fortify will make a new attempt Fortify_SetNewFailRate(int Percent) - Fortify will make a new attempt
"fail" this "Percent" of the time, even if the memory IS available. Useful "fail" this "Percent" of the time, even if the memory IS available. Useful
to "stress-test" an application. Returns the old value. The fail rate to "stress-test" an application. Returns the old value. The fail rate
defaults to 0. defaults to 0.
DIAGNOSTIC FUNCTIONS DIAGNOSTIC FUNCTIONS
-------------------- --------------------
Fortify also provides some additional diagnostic functions which can be Fortify also provides some additional diagnostic functions which can be
used to track down memory corruption and memory leaks. If Fortify is used to track down memory corruption and memory leaks. If Fortify is
disabled, these functions do nothing. If calling these functions directly disabled, these functions do nothing. If calling these functions directly
from a debugger, remember to add the "char *file" and "unsigned long line" from a debugger, remember to add the "char *file" and "unsigned long line"
paramters to each of the calls. (The ZFortify versions have a paramters to each of the calls. (The ZFortify versions have a
ZFortify_ prefix, of course). ZFortify_ prefix, of course).
Fortify_CheckPointer(void *uptr) - Returns true if the uptr points to a Fortify_CheckPointer(void *uptr) - Returns true if the uptr points to a
valid piece of Fortify'd memory. The memory must be on Fortify's list, and valid piece of Fortify'd memory. The memory must be on Fortify's list, and
it's sentinals must be in tact. If anything is wrong, an error message is it's sentinals must be in tact. If anything is wrong, an error message is
issued (Note - if Fortify is disabled, this function always returns true). issued (Note - if Fortify is disabled, this function always returns true).
Fortify_CheckAllMemory() - Checks the sentinals of all malloc'd memory. Fortify_CheckAllMemory() - Checks the sentinals of all malloc'd memory.
Returns the number of blocks that failed. (If Fortify is disabled, this Returns the number of blocks that failed. (If Fortify is disabled, this
function always returns 0). function always returns 0).
Fortify_OutputAllMemory() - Outputs the entire list of currently Fortify_OutputAllMemory() - Outputs the entire list of currently
allocated memory. For each block is output it's Address, Size, the allocated memory. For each block is output it's Address, Size, the
SourceFile and Line that allocated it, and the fortify scope from within it SourceFile and Line that allocated it, and the fortify scope from within it
was allocated. If there is no memory on the list, this function outputs was allocated. If there is no memory on the list, this function outputs
nothing. It returns the number of blocks on the list, unless Fortify has nothing. It returns the number of blocks on the list, unless Fortify has
been disabled, in which case it always returns 0. been disabled, in which case it always returns 0.
Fortify_DumpAllMemory(scope) - Just like Fortify_OutputAllMemory, Fortify_DumpAllMemory(scope) - Just like Fortify_OutputAllMemory,
except all memory inside the given scope is output, and a hex dump of each except all memory inside the given scope is output, and a hex dump of each
block is included in the output. block is included in the output.
Fortify_EnterScope() - enters a level of fortify scope. Returns the Fortify_EnterScope() - enters a level of fortify scope. Returns the
new scope level. new scope level.
Fortify_LeaveScope() - leaves a level of fortify scope, it also prints Fortify_LeaveScope() - leaves a level of fortify scope, it also prints
a dump of all memory allocated within the scope being left. This can be a dump of all memory allocated within the scope being left. This can be
very useful in tracking down memory leaks in a part of a program. If you very useful in tracking down memory leaks in a part of a program. If you
place a EnterScope/LeaveScope pair around a set of functions that should place a EnterScope/LeaveScope pair around a set of functions that should
have no memory allocated when it's done, Fortify will let you know if this have no memory allocated when it's done, Fortify will let you know if this
isn't the case. isn't the case.
PROBLEMS WITH THE new AND delete MACROS PROBLEMS WITH THE new AND delete MACROS
--------------------------------------- ---------------------------------------
Due to limitations of the preprocessor, getting caller sourcecode Due to limitations of the preprocessor, getting caller sourcecode
information isn't as easy as it is for malloc() and free(). The macro for information isn't as easy as it is for malloc() and free(). The macro for
"new" which adds this information onto the new call causes syntax errors if "new" which adds this information onto the new call causes syntax errors if
you try to declare a custom new operator. The actual Fortifying works you try to declare a custom new operator. The actual Fortifying works
fine, it's just the macro expansion which causes problems. fine, it's just the macro expansion which causes problems.
If this happens, you will need to place #undef's and #define's around If this happens, you will need to place #undef's and #define's around
the offending code (sorry). Alternatively, you can not #include the offending code (sorry). Alternatively, you can not #include
"zfortify.hpp" for the offending file. But remember that none of the "zfortify.hpp" for the offending file. But remember that none of the
allocation done in that file will have sourcecode information. allocation done in that file will have sourcecode information.
eg. eg.
#undef new #undef new
void *X::operator new(size_t) { return malloc(size_t); } void *X::operator new(size_t) { return malloc(size_t); }
#define new Fortify_New #define new Fortify_New
Due to a limitation with delete, Fortify has limited information about Due to a limitation with delete, Fortify has limited information about
where delete is being called called from, and so the the line and source where delete is being called called from, and so the the line and source
information will often say "delete.0". If a delete is occuring from within information will often say "delete.0". If a delete is occuring from within
another delete, Fortify will always endeavour to report the highest level another delete, Fortify will always endeavour to report the highest level
delete as the caller. delete as the caller.
It should be possible to replace the "new.0" and "delete.0" with the It should be possible to replace the "new.0" and "delete.0" with the
return address of the function, which would be useful when in a debugger, return address of the function, which would be useful when in a debugger,
but this would be highly architecture dependant, so I leave that as an but this would be highly architecture dependant, so I leave that as an
exercise for the students :-). exercise for the students :-).
WHEN TO USE FORTIFY WHEN TO USE FORTIFY
------------------- -------------------
The simple answer to this is "All The Time". You should never be The simple answer to this is "All The Time". You should never be
without Fortify when you're actually developing software. It will detect without Fortify when you're actually developing software. It will detect
your bugs _as_you_write_them_, which makes them a lot easier to find. One your bugs _as_you_write_them_, which makes them a lot easier to find. One
programmer who recently started using Fortify when he had a very strange programmer who recently started using Fortify when he had a very strange
memory problem, spent at least 3 or 4 days tracking down _other_ memory memory problem, spent at least 3 or 4 days tracking down _other_ memory
corruption bugs that he wasn't even aware of before the program would stay corruption bugs that he wasn't even aware of before the program would stay
up long enough to get to his original problem. If he'd been using Fortify up long enough to get to his original problem. If he'd been using Fortify
from the beginning, this wouldn't have been a problem. from the beginning, this wouldn't have been a problem.
Leave fortify enabled until the final test and release of your Leave fortify enabled until the final test and release of your
software. You probably won't want some of the slower options, such as software. You probably won't want some of the slower options, such as
CHECK_ALL_MEMORY_ON_FREE, and PARANOID_FREE. With the exception of those CHECK_ALL_MEMORY_ON_FREE, and PARANOID_FREE. With the exception of those
options, Fortify doesn't have a great deal of overhead. If posing a great options, Fortify doesn't have a great deal of overhead. If posing a great
problem, this overhead can be greatly reduced by cutting down on the size problem, this overhead can be greatly reduced by cutting down on the size
of the fortifications, and turning off the pre/post fills, but each thing of the fortifications, and turning off the pre/post fills, but each thing
you turn off gives fortify less information to work with in tracking your you turn off gives fortify less information to work with in tracking your
bugs. bugs.

View File

@ -393,7 +393,7 @@ static int FourMessStoreIntern(pSICSOBJ self, SConnection * pCon,
double fHkl[3], double fPosition[4], char *extra) double fHkl[3], double fPosition[4], char *extra)
{ {
pFourMess priv = self->pPrivate; pFourMess priv = self->pPrivate;
float fSum, fSigma, fTemp, fStep = .0, fPreset =.0; float fSum, fSigma, fTemp, fMF, fStep = .0, fPreset =.0;
int i, iLF, iRet, iNP, ii; int i, iLF, iRet, iNP, ii;
long *lCounts = NULL; long *lCounts = NULL;
pEVControl pEva = NULL; pEVControl pEva = NULL;
@ -411,6 +411,7 @@ static int FourMessStoreIntern(pSICSOBJ self, SConnection * pCon,
SCWrite(pCon, "ERROR: store: no files open", eLogError); SCWrite(pCon, "ERROR: store: no files open", eLogError);
return 0; return 0;
} }
priv->count++;
/* get necessary data */ /* get necessary data */
fSum = 0.; fSum = 0.;
@ -485,6 +486,23 @@ static int FourMessStoreIntern(pSICSOBJ self, SConnection * pCon,
iRet = EVCGetPos(pEva, pCon, &fTemp); iRet = EVCGetPos(pEva, pCon, &fTemp);
} }
/* get mf */
fMF = -777.77;
pEva = (pEVControl) FindCommandData(pServ->pSics, "mf",
"Environment Controller");
if (pEva == NULL) {
pPtr = (pDummy) FindCommandData(pServ->pSics, "mf",
"RemObject");
if (pPtr != NULL) {
pDriv = pPtr->pDescriptor->GetInterface(pPtr, DRIVEID);
if (pDriv != NULL) {
fMF = pDriv->GetValue(pPtr, pCon);
}
}
} else {
iRet = EVCGetPos(pEva, pCon, &fMF);
}
/* write profile */ /* write profile */
if (priv->profFile) { if (priv->profFile) {
/* collect data */ /* collect data */
@ -492,12 +510,16 @@ static int FourMessStoreIntern(pSICSOBJ self, SConnection * pCon,
GetScanVarStep(priv->pScanner, 0, &fStep); GetScanVarStep(priv->pScanner, 0, &fStep);
fPreset = GetScanPreset(priv->pScanner); fPreset = GetScanPreset(priv->pScanner);
prot = getProtonAverage(priv); prot = getProtonAverage(priv);
/*
They rather wanted fMF in place of the proton average which fell victim to the
monitor assignement chaos anyway.
*/
if(extra == NULL){ if(extra == NULL){
fprintf(priv->profFile, "%3d %7.4f %9.0f %7.3f %12f %s\n", iNP, fStep, fprintf(priv->profFile, "%3d %7.4f %9.0f %7.3f %12f %s\n", iNP, fStep,
fPreset, fTemp, prot, pBueffel); fPreset, fTemp, fMF, pBueffel);
} else { } else {
fprintf(priv->profFile, "%3d %7.4f %9.0f %7.3f %12f %s %s\n", iNP, fStep, fprintf(priv->profFile, "%3d %7.4f %9.0f %7.3f %12f %s %s\n", iNP, fStep,
fPreset, fTemp, prot, extra, pBueffel); fPreset, fTemp, fMF, pBueffel,extra);
} }
for (i = 0; i < iNP; i++) { for (i = 0; i < iNP; i++) {
for (ii = 0; ii < 10 && i < iNP; ii++) { for (ii = 0; ii < 10 && i < iNP; ii++) {

View File

@ -138,6 +138,9 @@ void DeleteNodeData(pHdb node)
if (node->name != NULL) { if (node->name != NULL) {
free(node->name); free(node->name);
} }
if (node->path != NULL) {
free(node->path);
}
ReleaseHdbValue(&node->value); ReleaseHdbValue(&node->value);
node->magic = 000000; node->magic = 000000;
@ -601,7 +604,7 @@ int compareHdbValue(hdbValue v1, hdbValue v2)
} }
break; break;
case HIPFLOAT: case HIPFLOAT:
if (ABS(v1.v.doubleValue - v2.v.doubleValue) < .01) { if (ABS(v1.v.doubleValue - v2.v.doubleValue) < .0001) { /* DFC */
return 1; return 1;
} else { } else {
return 0; return 0;
@ -895,6 +898,7 @@ char *GetHipadabaPath(pHdb node)
strcat(pPtr, "/"); strcat(pPtr, "/");
strcat(pPtr, nodeStack[i]->name); strcat(pPtr, nodeStack[i]->name);
} }
node->path = pPtr;
return pPtr; return pPtr;
} }
@ -1167,6 +1171,16 @@ void SetHdbProperty(pHdb node, char *key, char *value)
} }
} }
/*---------------------------------------------------------------------------*/
int HasHdbProperty(pHdb node, char *key)
{
if (node != NULL && node->properties != NULL) {
return StringDictExists(node->properties, key);
} else {
return 0;
}
}
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
int GetHdbProperty(pHdb node, char *key, char *value, int len) int GetHdbProperty(pHdb node, char *key, char *value, int len)
{ {
@ -1180,7 +1194,7 @@ int GetHdbProperty(pHdb node, char *key, char *value, int len)
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
char *GetHdbProp(pHdb node, char *key) char *GetHdbProp(pHdb node, char *key)
{ {
if (node != NULL && node->properties != NULL) { if (node != NULL && isHdbNodeValid(node) && node->properties != NULL) {
return StringDictGetShort(node->properties, key); return StringDictGetShort(node->properties, key);
} else { } else {
return NULL; return NULL;

View File

@ -72,6 +72,7 @@ typedef struct __hipadaba {
struct __hipadaba *next; struct __hipadaba *next;
struct __hdbcallback *callBackChain; struct __hdbcallback *callBackChain;
char *name; char *name;
char *path;
hdbValue value; hdbValue value;
int iprotected; int iprotected;
pStringDict properties; pStringDict properties;
@ -446,6 +447,13 @@ void SetHdbProperty(pHdb node, char *key, char *value);
* @param len The length of value * @param len The length of value
* @return 0 on failure, 1 on success * @return 0 on failure, 1 on success
*/ */
/**
* Check if a property exists
* @param node The node to get the property from
* @param key The properties key
* @return 1 or 0 for true or false
*/
int HasHdbProperty(pHdb node, char *key);
int GetHdbProperty(pHdb node, char *key, char *value, int len); int GetHdbProperty(pHdb node, char *key, char *value, int len);
/** /**
* get the value of a property * get the value of a property

View File

@ -47,6 +47,7 @@
#include "ifile.h" #include "ifile.h"
/*====================== Locals ============================================*/ /*====================== Locals ============================================*/
IPair *pSICSOptions = NULL;
static IPair *CreateNewEntry(char *name, char *val, IPair * pN) static IPair *CreateNewEntry(char *name, char *val, IPair * pN)
{ {

View File

@ -242,6 +242,9 @@ static int DriveTaskFunc(void *data)
ExeInterest(pServ->pExecutor,taskData->name, "finished with problem"); ExeInterest(pServ->pExecutor,taskData->name, "finished with problem");
} }
traceSys("drive","DriveTask %s finished with state %d", taskData->name,status); traceSys("drive","DriveTask %s finished with state %d", taskData->name,status);
if(taskData->pCon->transID > 100000) {
SCPrintf(taskData->pCon,eLog,"TASKEND %d", taskData->pCon->transID);
}
return 0; return 0;
} }
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
@ -272,6 +275,9 @@ long StartDriveTask(void *obj, SConnection *pCon, char *name, float fTarget)
ExeInterest(pServ->pExecutor,name,"started"); ExeInterest(pServ->pExecutor,name,"started");
DevexecLog("START",name); DevexecLog("START",name);
InvokeNewTarget(pServ->pExecutor,name,fTarget); InvokeNewTarget(pServ->pExecutor,name,fTarget);
if(pCon->transID > 100000) {
SCPrintf(pCon,eLog,"TASKSTART %d", pCon->transID);
}
taskData->id = DRIVEID; taskData->id = DRIVEID;
taskData->obj = obj; taskData->obj = obj;
@ -393,6 +399,9 @@ static int CountTaskFunc(void *data)
ExeInterest(pServ->pExecutor,taskData->name, "finished with problem"); ExeInterest(pServ->pExecutor,taskData->name, "finished with problem");
} }
traceSys("count","CountTask %s finished with state %d", taskData->name,status); traceSys("count","CountTask %s finished with state %d", taskData->name,status);
if(taskData->pCon->transID > 100000) {
SCPrintf(taskData->pCon,eLog,"TASKEND %d", taskData->pCon->transID);
}
return 0; return 0;
} }
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
@ -418,6 +427,9 @@ long StartCountTask(void *obj, SConnection *pCon, char *name)
} }
ExeInterest(pServ->pExecutor,name,"started"); ExeInterest(pServ->pExecutor,name,"started");
DevexecLog("START",name); DevexecLog("START",name);
if(pCon->transID > 100000) {
SCPrintf(pCon,eLog,"TASKSTART %d", pCon->transID);
}
taskData->id = COUNTID; taskData->id = COUNTID;
taskData->obj = obj; taskData->obj = obj;

View File

@ -109,6 +109,8 @@
void *pUserData, KillFuncIT pKill); void *pUserData, KillFuncIT pKill);
int RemoveCallback(pICallBack pInterface, long iID); int RemoveCallback(pICallBack pInterface, long iID);
int RemoveCallback2(pICallBack pInterface, void *pUserData); int RemoveCallback2(pICallBack pInterface, void *pUserData);
int RemoveCallbackUsr(pICallBack self, SICSCallBack pFunc,
int (*userfunc)(const void* pContext, const void* pUserData), void *pCtx);
int RemoveCallbackCon(pICallBack pInterface, SConnection *pCon); int RemoveCallbackCon(pICallBack pInterface, SConnection *pCon);
int CallbackScript(SConnection *pCon, SicsInterp *pSics, void *pData, int CallbackScript(SConnection *pCon, SicsInterp *pSics, void *pData,

1
lld.c
View File

@ -89,6 +89,7 @@ static int ListInit(int List, int ItemSize)
*/ */
Tmp = NODE_MALLOC(List); Tmp = NODE_MALLOC(List);
if (NULL == Tmp) { if (NULL == Tmp) {
Tmp = ListControl[List].first;
NODE_FREE(Tmp); /* no need to cause memory leaks */ NODE_FREE(Tmp); /* no need to cause memory leaks */
ListControl[List].first = NULL; /* or other errors */ ListControl[List].first = NULL; /* or other errors */
return ERR_MEMORY; /* even if we're in trouble ... */ return ERR_MEMORY; /* even if we're in trouble ... */

View File

@ -397,6 +397,9 @@ static int LoggerMakeDir(char *path)
return 0; /* mkdir failed */ return 0; /* mkdir failed */
snprintf(buffer, sizeof buffer, "%s", path); snprintf(buffer, sizeof buffer, "%s", path);
lpath = strlen(buffer); lpath = strlen(buffer);
/* Discard any trailing slash characters */
while (lpath > 0 && buffer[lpath - 1] == '/')
buffer[--lpath] = '\0';
do { do {
slash = strrchr(buffer, '/'); slash = strrchr(buffer, '/');
if (!slash) if (!slash)

View File

@ -218,9 +218,7 @@ static int LogReader(SConnection * pCon, SicsInterp * pSics, void *pData,
int argc, char *argv[]) int argc, char *argv[])
{ {
/* Usage: /* Usage:
graph <start time> <end time> [ none <none value> ] np <number of points> <variable> [<variable> ...] graph <start time> <end time> [ none <none value> | text | np <number of points> ] <variable> [<variable> ...]
graph <start time> <end time> text <variable>
graph <start time> <end time> <step> <variable> [<variable> ...]
<start time> and <end time> are seconds since epoch (unix time) or, if the value <start time> and <end time> are seconds since epoch (unix time) or, if the value
is below one day, a time relative to the actual time is below one day, a time relative to the actual time
@ -230,15 +228,13 @@ static int LogReader(SConnection * pCon, SicsInterp * pSics, void *pData,
<number of points> is the maximal number of points to be returned. If more values <number of points> is the maximal number of points to be returned. If more values
are present and the values are numeric, the data is reduced. If the data is not are present and the values are numeric, the data is reduced. If the data is not
numeric, the last values may be skipped in order to avoid overflow. numeric, the last values may be skipped in order to avoid overflow.
If np is not given, it is assumed to be very high.
<variable> is the name of a variable (several vaiables may be given). <variable> is the name of a variable (several vaiables may be given).
Note that slashes are converted to dots, and that the first slash is ignored. Note that slashes are converted to dots, and that the first slash is ignored.
The seconds variant is for text values, which can not be reduced. In any case, all values "text" means that the values are not numeric, in this case np is not needed
are returned. and by default infinitely high
The third variant is old style and can be replaced by the first variant, where
<number of points> = (<start time> - <end time>) / <step> + 2
Output format: Output format:
@ -308,15 +304,16 @@ Statistics *old;
to += now; to += now;
} }
iarg = 3; iarg = 3;
type0 = NUMERIC;
while (1) { while (1) {
if (iarg >= argc) if (iarg >= argc)
goto illarg; goto illarg;
if (strcasecmp(argv[iarg], "text") == 0) { /* non-numeric values */ if (strcasecmp(argv[iarg], "text") == 0) { /* non-numeric values */
iarg++; iarg++;
step = 1; step = 1;
type0 = TEXT;
np = to - from + 2; np = to - from + 2;
break; type0 = TEXT;
/* break; */
} else if (strcasecmp(argv[iarg], "none") == 0) { /* none */ } else if (strcasecmp(argv[iarg], "none") == 0) { /* none */
iarg++; iarg++;
if (iarg >= argc) if (iarg >= argc)
@ -327,7 +324,6 @@ Statistics *old;
iarg++; iarg++;
if (iarg >= argc) if (iarg >= argc)
goto illarg; goto illarg;
type0 = NUMERIC;
np = strtol(argv[iarg], &p, 0); np = strtol(argv[iarg], &p, 0);
if (p == argv[iarg]) if (p == argv[iarg])
goto illarg; goto illarg;
@ -341,14 +337,9 @@ Statistics *old;
} }
break; break;
} else { } else {
step = strtol(argv[iarg], &p, 0); np = to - from + 2;
if (p == argv[iarg]) step = 1;
goto illarg; break;
iarg++;
if (step <= 0)
step = 1;
type0 = NUMERIC;
np = (from - to) / step + 2;
} }
} }
if (step <= 0) if (step <= 0)

View File

@ -118,6 +118,11 @@ static int LogSetup(SConnection * pCon, SicsInterp * pSics, void *pData,
LoggerChange(logger, period, name); LoggerChange(logger, period, name);
} else { } else {
logger = LoggerMake(name, period, !numeric); logger = LoggerMake(name, period, !numeric);
/* If that failed, we cannot continue - it crashes in the callback */
if (logger == NULL) {
SCPrintf(pCon, eError, "ERROR: logger %s not created", argv[1]);
return 0;
}
LoggerSetNumeric(logger, numeric); LoggerSetNumeric(logger, numeric);
SetHdbProperty(node, "logger_name", name); SetHdbProperty(node, "logger_name", name);
cb = MakeHipadabaCallback(LoggerUpdateCallback, logger, cb = MakeHipadabaCallback(LoggerUpdateCallback, logger,

View File

@ -68,6 +68,7 @@
#include "ifile.h" #include "ifile.h"
#include "Dbg.h" #include "Dbg.h"
#include "servlog.h" #include "servlog.h"
#include "sicsglobal.h"
#include "stringdict.h" #include "stringdict.h"
#include "exeman.h" #include "exeman.h"
#include "nxcopy.h" #include "nxcopy.h"
@ -493,6 +494,7 @@ int MacroFileEval(SConnection * pCon, SicsInterp * pInter, void *pData,
iRun = 0; iRun = 0;
} }
if (iChar == (int) '\n') { if (iChar == (int) '\n') {
iLine++;
pBueffel[i] = (char) iChar; pBueffel[i] = (char) iChar;
pBueffel[i + 1] = '\0'; pBueffel[i + 1] = '\0';
Tcl_DStringAppend(&command, pBueffel, -1); Tcl_DStringAppend(&command, pBueffel, -1);
@ -500,13 +502,12 @@ int MacroFileEval(SConnection * pCon, SicsInterp * pInter, void *pData,
if (Tcl_CommandComplete(pCom)) { if (Tcl_CommandComplete(pCom)) {
FirstWord(pCom, pBueffel); FirstWord(pCom, pBueffel);
if (FindCommand(pInter, pBueffel) != NULL) { if (FindCommand(pInter, pBueffel) != NULL) {
snprintf(pBueffel,sizeof(pBueffel)-1, "%s:%d>> %s", pFile, iLine, pCom); snprintf(pBueffel,sizeof(pBueffel)-1, "%s:%d>> %s", argv[1], iLine, pCom);
SCWrite(pCon, pBueffel, eLog); SCWrite(pCon, pBueffel, eLog);
if (pWhere != NULL) { if (pWhere != NULL) {
free(pWhere); free(pWhere);
} }
pWhere = strdup(pBueffel); pWhere = strdup(pBueffel);
iLine++;
} }
iRet = Tcl_Eval(pTcl, pCom); iRet = Tcl_Eval(pTcl, pCom);
if (iRet != TCL_OK) { if (iRet != TCL_OK) {

View File

@ -47,7 +47,7 @@ SOBJ = network.o ifile.o conman.o SCinter.o splitter.o passwd.o \
histmemsec.o sansbc.o sicsutil.o strlutil.o genbinprot.o trace.o\ histmemsec.o sansbc.o sicsutil.o strlutil.o genbinprot.o trace.o\
singlebinb.o taskobj.o sctcomtask.o tasmono.o multicountersec.o \ singlebinb.o taskobj.o sctcomtask.o tasmono.o multicountersec.o \
messagepipe.o sicsget.o remoteobject.o pmacprot.o charbychar.o binprot.o \ messagepipe.o sicsget.o remoteobject.o pmacprot.o charbychar.o binprot.o \
cnvrt.o cnvrt.o tclClock.o tclDate.o tclUnixTime.o
MOTOROBJ = motor.o simdriv.o MOTOROBJ = motor.o simdriv.o
COUNTEROBJ = countdriv.o simcter.o counter.o COUNTEROBJ = countdriv.o simcter.o counter.o

View File

@ -1,20 +1,20 @@
1.1 2 3 4 5 6 7 8 9 9 1.1 2 3 4 5 6 7 8 9 9
2 3.1 4 5 6 7 8 9 9 8 2 3.1 4 5 6 7 8 9 9 8
3 4 5.1 6 7 8 9 9 8 7 3 4 5.1 6 7 8 9 9 8 7
3 4 5 6.1 7 8 9 9 8 7 3 4 5 6.1 7 8 9 9 8 7
1 2 3 4 5 7.2 7 8 9 9 1 2 3 4 5 7.2 7 8 9 9
1 2 3 4 1 6 7 8.3 9 9 1 2 3 4 1 6 7 8.3 9 9
6 2 3 4 5 6 7 8 9.8 9 6 2 3 4 5 6 7 8 9.8 9
1 2 3 3 5 6 7 8 9 9.8 1 2 3 3 5 6 7 8 9 9.8
1 2 3 4 6 6 7 8 9 9 1 2 3 4 6 6 7 8 9 9
6 2 3 4 5 4 7 8 9 9 6 2 3 4 5 4 7 8 9 9
3 3
1 1
4 4
1 1
2 2
3 3
1 1
1 1
2 2
6 6

View File

@ -1,62 +1,62 @@
#------------------------------------------------------------------------------ #------------------------------------------------------------------------------
# file: makefile.msc # file: makefile.msc
# desc: makefile for matrix library package under Microsoft C/C++ v7.0 # desc: makefile for matrix library package under Microsoft C/C++ v7.0
# by: patrick ko # by: patrick ko
# date: 16 Apr 94 # date: 16 Apr 94
# #
# note: a slim matrix library matrix.lib will be generated # note: a slim matrix library matrix.lib will be generated
#------------------------------------------------------------------------------ #------------------------------------------------------------------------------
OBJS = matcreat.obj matdump.obj materr.obj matadd.obj matsub.obj \ OBJS = matcreat.obj matdump.obj materr.obj matadd.obj matsub.obj \
matmul.obj matinv.obj matsolve.obj matdet.obj mattran.obj matdurbn.obj \ matmul.obj matinv.obj matsolve.obj matdet.obj mattran.obj matdurbn.obj \
mattoepz.obj matsubx.obj mattoepz.obj matsubx.obj
CC = cl -c CC = cl -c
C = cl C = cl
demo.exe: demo.c matrix.lib demo.exe: demo.c matrix.lib
$(C) demo.c matrix.lib $(C) demo.c matrix.lib
matrix.lib: $(OBJS) matrix.lib: $(OBJS)
lib matrix +matcreat +matdump +materr +matadd.obj ,, lib matrix +matcreat +matdump +materr +matadd.obj ,,
lib matrix +matsub +matmul +matinv +matsolve +matdet.obj ,, lib matrix +matsub +matmul +matinv +matsolve +matdet.obj ,,
lib matrix +mattran +matdurbn +mattoepz +matsubx ,, lib matrix +mattran +matdurbn +mattoepz +matsubx ,,
matcreat.obj: matcreat.c matrix.h matcreat.obj: matcreat.c matrix.h
$(CC) matcreat.c $(CC) matcreat.c
matdump.obj: matdump.c matrix.h matdump.obj: matdump.c matrix.h
$(CC) matdump.c $(CC) matdump.c
materr.obj: materr.c matrix.h materr.obj: materr.c matrix.h
$(CC) materr.c $(CC) materr.c
matadd.obj: matadd.c matrix.h matadd.obj: matadd.c matrix.h
$(CC) matadd.c $(CC) matadd.c
matsub.obj: matsub.c matrix.h matsub.obj: matsub.c matrix.h
$(CC) matsub.c $(CC) matsub.c
matmul.obj: matmul.c matrix.h matmul.obj: matmul.c matrix.h
$(CC) matmul.c $(CC) matmul.c
matinv.obj: matinv.c matrix.h matinv.obj: matinv.c matrix.h
$(CC) matinv.c $(CC) matinv.c
matsolve.obj: matsolve.c matrix.h matsolve.obj: matsolve.c matrix.h
$(CC) matsolve.c $(CC) matsolve.c
mattran.obj: mattran.c matrix.h mattran.obj: mattran.c matrix.h
$(CC) mattran.c $(CC) mattran.c
matdet.obj: matdet.c matrix.h matdet.obj: matdet.c matrix.h
$(CC) matdet.c $(CC) matdet.c
matdurbn.obj: matdurbn.c matrix.h matdurbn.obj: matdurbn.c matrix.h
$(CC) matdurbn.c $(CC) matdurbn.c
mattoepz.obj: mattoepz.c matrix.h mattoepz.obj: mattoepz.c matrix.h
$(CC) mattoepz.c $(CC) mattoepz.c
matsubx.obj: matsubx.c matrix.h matsubx.obj: matsubx.c matrix.h
$(CC) matsubx.c $(CC) matsubx.c

View File

@ -1,74 +1,74 @@
#------------------------------------------------------------------------------ #------------------------------------------------------------------------------
# file: makefile.tc # file: makefile.tc
# desc: makefile for matrix library package under Turbo C v2.0 # desc: makefile for matrix library package under Turbo C v2.0
# by: patrick ko # by: patrick ko
# date: 16 Apr 94 # date: 16 Apr 94
# #
# note: a slim matrix library matrix.lib will be generated # note: a slim matrix library matrix.lib will be generated
#------------------------------------------------------------------------------ #------------------------------------------------------------------------------
DRIVE = C: DRIVE = C:
OBJS = matcreat.obj matdump.obj materr.obj matadd.obj matsub.obj \ OBJS = matcreat.obj matdump.obj materr.obj matadd.obj matsub.obj \
matmul.obj matinv.obj matsolve.obj matdet.obj mattran.obj matdurbn.obj \ matmul.obj matinv.obj matsolve.obj matdet.obj mattran.obj matdurbn.obj \
mattoepz.obj matsubx.obj mattoepz.obj matsubx.obj
LIB = -L$(DRIVE)\TC\LIB LIB = -L$(DRIVE)\TC\LIB
INC = -I$(DRIVE)\TC\INCLUDE INC = -I$(DRIVE)\TC\INCLUDE
CC = tcc -c -mh $(INC) CC = tcc -c -mh $(INC)
C = tcc -mh $(LIB) $(INC) C = tcc -mh $(LIB) $(INC)
LL = tlib matrix.lib LL = tlib matrix.lib
demo.exe: demo.c $(OBJS) demo.exe: demo.c $(OBJS)
$(C) demo.c matrix.lib $(C) demo.c matrix.lib
matcreat.obj: matcreat.c matrix.h matcreat.obj: matcreat.c matrix.h
$(CC) matcreat.c $(CC) matcreat.c
$(LL) -+matcreat.obj $(LL) -+matcreat.obj
matdump.obj: matdump.c matrix.h matdump.obj: matdump.c matrix.h
$(CC) matdump.c $(CC) matdump.c
$(LL) -+matdump.obj $(LL) -+matdump.obj
materr.obj: materr.c matrix.h materr.obj: materr.c matrix.h
$(CC) materr.c $(CC) materr.c
$(LL) -+materr.obj $(LL) -+materr.obj
matadd.obj: matadd.c matrix.h matadd.obj: matadd.c matrix.h
$(CC) matadd.c $(CC) matadd.c
$(LL) -+matadd.obj $(LL) -+matadd.obj
matsub.obj: matsub.c matrix.h matsub.obj: matsub.c matrix.h
$(CC) matsub.c $(CC) matsub.c
$(LL) -+matsub.obj $(LL) -+matsub.obj
matmul.obj: matmul.c matrix.h matmul.obj: matmul.c matrix.h
$(CC) matmul.c $(CC) matmul.c
$(LL) -+matmul.obj $(LL) -+matmul.obj
matinv.obj: matinv.c matrix.h matinv.obj: matinv.c matrix.h
$(CC) matinv.c $(CC) matinv.c
$(LL) -+matinv.obj $(LL) -+matinv.obj
matsolve.obj: matsolve.c matrix.h matsolve.obj: matsolve.c matrix.h
$(CC) matsolve.c $(CC) matsolve.c
$(LL) -+matsolve.obj $(LL) -+matsolve.obj
mattran.obj: mattran.c matrix.h mattran.obj: mattran.c matrix.h
$(CC) mattran.c $(CC) mattran.c
$(LL) -+mattran.obj $(LL) -+mattran.obj
matdet.obj: matdet.c matrix.h matdet.obj: matdet.c matrix.h
$(CC) matdet.c $(CC) matdet.c
$(LL) -+matdet.obj $(LL) -+matdet.obj
matdurbn.obj: matdurbn.c matrix.h matdurbn.obj: matdurbn.c matrix.h
$(CC) matdurbn.c $(CC) matdurbn.c
$(LL) -+matdurbn.obj $(LL) -+matdurbn.obj
mattoepz.obj: mattoepz.c matrix.h mattoepz.obj: mattoepz.c matrix.h
$(CC) mattoepz.c $(CC) mattoepz.c
$(LL) -+mattoepz.obj $(LL) -+mattoepz.obj
matsubx.obj: matsubx.c matrix.h matsubx.obj: matsubx.c matrix.h
$(CC) matsubx.c $(CC) matsubx.c
$(LL) -+matsubx.obj $(LL) -+matsubx.obj

View File

@ -1,54 +1,54 @@
#------------------------------------------------------------------------------ #------------------------------------------------------------------------------
# file: makefile.ux # file: makefile.ux
# desc: makefile for matrix library package under Unix # desc: makefile for matrix library package under Unix
# by: patrick ko # by: patrick ko
# date: 16 Apr 94 # date: 16 Apr 94
#------------------------------------------------------------------------------ #------------------------------------------------------------------------------
OBJS = matcreat.o matdump.o materr.o matadd.o matsub.o \ OBJS = matcreat.o matdump.o materr.o matadd.o matsub.o \
matmul.o matinv.o matsolve.o mattran.o matdet.o mattoepz.o matdurbn.o matmul.o matinv.o matsolve.o mattran.o matdet.o mattoepz.o matdurbn.o
CC = cc -c CC = cc -c
C = cc C = cc
CO = -lm -g CO = -lm -g
demo: demo.c $(OBJS) demo: demo.c $(OBJS)
$(C) demo.c -o demo $(OBJS) $(CO) $(C) demo.c -o demo $(OBJS) $(CO)
matcreat.o: matcreat.c matrix.h matcreat.o: matcreat.c matrix.h
$(CC) matcreat.c $(CC) matcreat.c
matdump.o: matdump.c matrix.h matdump.o: matdump.c matrix.h
$(CC) matdump.c $(CC) matdump.c
materr.o: materr.c matrix.h materr.o: materr.c matrix.h
$(CC) materr.c $(CC) materr.c
matadd.o: matadd.c matrix.h matadd.o: matadd.c matrix.h
$(CC) matadd.c $(CC) matadd.c
matsub.o: matsub.c matrix.h matsub.o: matsub.c matrix.h
$(CC) matsub.c $(CC) matsub.c
matmul.o: matmul.c matrix.h matmul.o: matmul.c matrix.h
$(CC) matmul.c $(CC) matmul.c
matinv.o: matinv.c matrix.h matinv.o: matinv.c matrix.h
$(CC) matinv.c $(CC) matinv.c
matsolve.o: matsolve.c matrix.h matsolve.o: matsolve.c matrix.h
$(CC) matsolve.c $(CC) matsolve.c
mattran.o: mattran.c matrix.h mattran.o: mattran.c matrix.h
$(CC) mattran.c $(CC) mattran.c
matdet.o: matdet.c matrix.h matdet.o: matdet.c matrix.h
$(CC) matdet.c $(CC) matdet.c
mattoepz.o: mattoepz.c matrix.h mattoepz.o: mattoepz.c matrix.h
$(CC) mattoepz.c $(CC) mattoepz.c
matdurbn.o: matdurbn.c matrix.h matdurbn.o: matdurbn.c matrix.h
$(CC) matdurbn.c $(CC) matdurbn.c
matsubx.o: matsubx.c matrix.h matsubx.o: matsubx.c matrix.h
$(CC) matsubx.c $(CC) matsubx.c

View File

@ -1,112 +1,112 @@
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Small Matrix Toolbox for C programmers Small Matrix Toolbox for C programmers
version 0.42 version 0.42
(Support Unix and DOS) (Support Unix and DOS)
by Patrick KO Shu-pui by Patrick KO Shu-pui
Copyright (c) 1992, 1993, 1994 All Rights Reserved. Copyright (c) 1992, 1993, 1994 All Rights Reserved.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
ADDRESS TO CONTACT: ADDRESS TO CONTACT:
fidonet: 6:700/132 BiG Programming Club fidonet: 6:700/132 BiG Programming Club
[852] 663-0223 19.2 kbps [852] 663-0223 19.2 kbps
[852] 663-0236 16.8 kbps [852] 663-0236 16.8 kbps
internet: pko@hk.super.net internet: pko@hk.super.net
mailing: Patrick Ko mailing: Patrick Ko
G.P.O. Box 7468 G.P.O. Box 7468
Hong Kong Hong Kong
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
MATRX042.ZIP contains MATRX042.ZIP contains
READ .ME - this file READ .ME - this file
DEMO .C - demo how to use this package DEMO .C - demo how to use this package
DEMO .DAT - demo data DEMO .DAT - demo data
DEMO .EXE - demo executable for DOS DEMO .EXE - demo executable for DOS
MAKEFILE.MSC - makefile for Microsoft C/C++ 7.0 on DOS MAKEFILE.MSC - makefile for Microsoft C/C++ 7.0 on DOS
MAKEFILE.TC - makefile for Turbo C 2.0 on DOS MAKEFILE.TC - makefile for Turbo C 2.0 on DOS
MAKEFILE.UX - makefile for Unix MAKEFILE.UX - makefile for Unix
MATRIX .DOC - matrix toolbox interface document MATRIX .DOC - matrix toolbox interface document
MATRIX .H - matrix header file (must include it) MATRIX .H - matrix header file (must include it)
MATADD .C - matrix addition MATADD .C - matrix addition
MATCREAT.C - matrix creation MATCREAT.C - matrix creation
MATDET .C - find minor, cofactor, determinant MATDET .C - find minor, cofactor, determinant
MATDUMP .C - matrix dump MATDUMP .C - matrix dump
MATERR .C - matrix error handling routine MATERR .C - matrix error handling routine
MATINV .C - matrix inversion MATINV .C - matrix inversion
MATMUL .C - matrix multiplication MATMUL .C - matrix multiplication
MATSOLVE.C - linear equations solver MATSOLVE.C - linear equations solver
MATSUB .C - matrix substraction MATSUB .C - matrix substraction
MATSUBX .C - submatrix operation MATSUBX .C - submatrix operation
MATTOEPZ.C - create symmetric Toeplitz matrix MATTOEPZ.C - create symmetric Toeplitz matrix
MATDURBN.C - Symmetrix Toeplitz matrix fast solving algorithm MATDURBN.C - Symmetrix Toeplitz matrix fast solving algorithm
MATTRAN .C - matrix transpose MATTRAN .C - matrix transpose
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
WHATS NEW in v0.1: WHATS NEW in v0.1:
- +, -, *, inverse matrix operations - +, -, *, inverse matrix operations
WHATS NEW in v0.2: WHATS NEW in v0.2:
- Linear equation solver - Linear equation solver
- C-programmer-friendly C sources - C-programmer-friendly C sources
WHATS NEW in v0.3: WHATS NEW in v0.3:
- better data structure (more Object-Oriented) - better data structure (more Object-Oriented)
- finding minors, cofactors, determinants - finding minors, cofactors, determinants
- Levinson-Durbin algorithm for symmetric Toeplitz matrix - Levinson-Durbin algorithm for symmetric Toeplitz matrix
WHATS NEW in v0.4: WHATS NEW in v0.4:
- Revised method for minors, cofactors and determinants - Revised method for minors, cofactors and determinants
whose time complexity is T(n^3) instead of nearly T(n!). whose time complexity is T(n^3) instead of nearly T(n!).
This is important when you want to find the determinant This is important when you want to find the determinant
of a matrix whose size is over 10 x 10. of a matrix whose size is over 10 x 10.
- submatrix operator - submatrix operator
- matrix formmated dump function - matrix formmated dump function
- brief matrix toolbox interface document included - brief matrix toolbox interface document included
WHATS NEW in v0.41: WHATS NEW in v0.41:
- bug fix for unit matrix creation - bug fix for unit matrix creation
WHATS NEW in v0.42: WHATS NEW in v0.42:
- support Microsoft C/C++ 7.0 - support Microsoft C/C++ 7.0
HOW TO COMPILE: HOW TO COMPILE:
1. All Unix environment - make -f makefile.ux 1. All Unix environment - make -f makefile.ux
2. DOS (Turbo C v2.0) - make -fmakefile.tc 2. DOS (Turbo C v2.0) - make -fmakefile.tc
3. DOS (Microsoft C/C++ v7.0) - nmake -fmakefile.msc 3. DOS (Microsoft C/C++ v7.0) - nmake -fmakefile.msc
REFERENCES REFERENCES
[1] Mary L.Boas, "Mathematical Methods in the Physical Sciene," [1] Mary L.Boas, "Mathematical Methods in the Physical Sciene,"
John Wiley & Sons, 2nd Ed., 1983. Chap 3. John Wiley & Sons, 2nd Ed., 1983. Chap 3.
[2] Kendall E.Atkinson, "An Introduction to Numberical Analysis," [2] Kendall E.Atkinson, "An Introduction to Numberical Analysis,"
John Wiley & Sons, 1978. John Wiley & Sons, 1978.
[3] Shuzo Saito, Kazuo Nakata, "Fundamentals of Speech Signal [3] Shuzo Saito, Kazuo Nakata, "Fundamentals of Speech Signal
Processing," Academic Press, 1985. Processing," Academic Press, 1985.
[4] Alfred V.Aho, John E.Hopcroft, Jeffrey D.Ullman, "The Design [4] Alfred V.Aho, John E.Hopcroft, Jeffrey D.Ullman, "The Design
and Analysis of Computer Algorithms," 1974. and Analysis of Computer Algorithms," 1974.
AUTHOR AUTHOR
All the sources are written by Patrick KO Shu Pui All the sources are written by Patrick KO Shu Pui
BiG Programming Club (6:700/132, fidonet) BiG Programming Club (6:700/132, fidonet)
=============================================================================== ===============================================================================
AUTHORIZATION NOTICE AUTHORIZATION NOTICE
This C source package MATRX042.ZIP is FREE for ACADEMIC purpose only. This C source package MATRX042.ZIP is FREE for ACADEMIC purpose only.
For COMMERCIAL use, authorization is required from the author. For COMMERCIAL use, authorization is required from the author.
Please send US$25 for registration. Please send US$25 for registration.
=============================================================================== ===============================================================================
DISCLAIMER (I hate this but I have to do that) DISCLAIMER (I hate this but I have to do that)
You are on your own risk - the author is not responsible for any lost due You are on your own risk - the author is not responsible for any lost due
to the use of this toolbox. to the use of this toolbox.
=============================================================================== ===============================================================================

View File

@ -1,92 +1,92 @@
/* /*
*----------------------------------------------------------------------------- *-----------------------------------------------------------------------------
* file: demo.c * file: demo.c
* desc: demostrate how to use Patrick's matrix toolbox * desc: demostrate how to use Patrick's matrix toolbox
* by: ko shu pui, patrick * by: ko shu pui, patrick
* date: 24 nov 91 v0.1 * date: 24 nov 91 v0.1
* revi: 14 may 92 v0.2 * revi: 14 may 92 v0.2
* 24 may 92 v0.4 * 24 may 92 v0.4
* ref: * ref:
* [1] Mary L.Boas, "Mathematical Methods in the Physical Sciene," * [1] Mary L.Boas, "Mathematical Methods in the Physical Sciene,"
* John Wiley & Sons, 2nd Ed., 1983. Chap 3. * John Wiley & Sons, 2nd Ed., 1983. Chap 3.
* *
* [2] Kendall E.Atkinson, "An Introduction to Numberical Analysis," * [2] Kendall E.Atkinson, "An Introduction to Numberical Analysis,"
* John Wiley & Sons, 1978. * John Wiley & Sons, 1978.
* *
* [3] Alfred V.Aho, John E.Hopcroft, Jeffrey D.Ullman, "The Design * [3] Alfred V.Aho, John E.Hopcroft, Jeffrey D.Ullman, "The Design
* and Analysis of Computer Algorithms," 1974. * and Analysis of Computer Algorithms," 1974.
* *
*----------------------------------------------------------------------------- *-----------------------------------------------------------------------------
*/ */
#include <stdio.h> #include <stdio.h>
#include <time.h> #include <time.h>
#include "matrix.h" #include "matrix.h"
int main() int main()
{ {
MATRIX A, B, X, M; MATRIX A, B, X, M;
FILE *fp; FILE *fp;
double result; double result;
time_t t1, t2; time_t t1, t2;
int tinv, tdet, tmul; int tinv, tdet, tmul;
A = mat_creat( 10, 10, UNDEFINED ); A = mat_creat( 10, 10, UNDEFINED );
B = mat_creat( 10, 1, UNDEFINED ); B = mat_creat( 10, 1, UNDEFINED );
if ((fp = fopen( "demo.dat", "r" )) == NULL) if ((fp = fopen( "demo.dat", "r" )) == NULL)
{ {
fprintf( stderr, "file cannot be opened\n" ); fprintf( stderr, "file cannot be opened\n" );
exit (0); exit (0);
} }
fgetmat( A, fp ); fgetmat( A, fp );
printf( "|- Matrix A -|\n"); printf( "|- Matrix A -|\n");
mat_dumpf( A, "%+06.1f " ); mat_dumpf( A, "%+06.1f " );
t1 = time(&t1); t1 = time(&t1);
result = mat_det(A); result = mat_det(A);
t2 = time(&t2); t2 = time(&t2);
tdet = t2 - t1; tdet = t2 - t1;
printf( "\n\nDet(A) = %f\n", result ); printf( "\n\nDet(A) = %f\n", result );
printf( "|- Inv A -|\n"); printf( "|- Inv A -|\n");
t1 = time(&t1); t1 = time(&t1);
X = mat_inv( A ); X = mat_inv( A );
t2 = time(&t2); t2 = time(&t2);
tinv = t2 - t1; tinv = t2 - t1;
if (X == NULL) if (X == NULL)
printf( "A is a singular matrix\n" ); printf( "A is a singular matrix\n" );
else else
{ {
mat_dumpf(X, "%+06.1f "); mat_dumpf(X, "%+06.1f ");
printf( "|- A x Inv A -|\n"); printf( "|- A x Inv A -|\n");
t1 = time(&t1); t1 = time(&t1);
M = mat_mul( X, A ); M = mat_mul( X, A );
t2 = time(&t2); t2 = time(&t2);
tmul = t2 - t1; tmul = t2 - t1;
mat_dumpf( M, "%+06.1f " ); mat_dumpf( M, "%+06.1f " );
mat_free(M); mat_free(M);
mat_free(X); mat_free(X);
} }
fgetmat( B, fp ); fgetmat( B, fp );
printf( "|- Matrix B -|\n"); printf( "|- Matrix B -|\n");
mat_dumpf( B, "%+06.1f " ); mat_dumpf( B, "%+06.1f " );
printf( "|- A x B -|\n"); printf( "|- A x B -|\n");
mat_free(mat_dumpf(mat_mul(A, B), "%+06.1f ")); mat_free(mat_dumpf(mat_mul(A, B), "%+06.1f "));
printf( "time for finding 10 x 10 matrix inversion is less than %d secs\n", tinv ); printf( "time for finding 10 x 10 matrix inversion is less than %d secs\n", tinv );
printf( "time for finding 10 x 10 matrix determinant is less than %d secs\n", tdet ); printf( "time for finding 10 x 10 matrix determinant is less than %d secs\n", tdet );
printf( "time for finding 10 x 10 matrix multiplication is less than %d secs\n", tmul ); printf( "time for finding 10 x 10 matrix multiplication is less than %d secs\n", tmul );
mat_free( A ); mat_free( A );
mat_free( B ); mat_free( B );
fclose(fp); fclose(fp);
} }
 

View File

@ -10,7 +10,7 @@
* %I * %I
* Written by: Kim Lefmann * Written by: Kim Lefmann
* Date: October 4, 1997 * Date: October 4, 1997
* Version: $Revision: 1.19 $ * Version: $Revision$
* Origin: Risoe * Origin: Risoe
* Release: McStas 1.6 * Release: McStas 1.6
* Modified to write monitor file for SICS: Mark Koennecke, June 2005 * Modified to write monitor file for SICS: Mark Koennecke, June 2005

View File

@ -10,7 +10,7 @@
* %I * %I
* Written by: Kim Lefmann * Written by: Kim Lefmann
* Date: Feb 3, 1998 * Date: Feb 3, 1998
* Version: $Revision: 1.2 $ * Version: $Revision$
* Origin: Risoe * Origin: Risoe
* Release: McStas 1.6 * Release: McStas 1.6
* *

View File

@ -30,9 +30,9 @@
* *
* Usage: Automatically embbeded in the c code. * Usage: Automatically embbeded in the c code.
* *
* $Id: dmcafter.c,v 1.1 2007/01/30 03:19:43 koennecke Exp $ * $Id$
* *
* $Log: dmcafter.c,v $ * $Log$
* Revision 1.1 2007/01/30 03:19:43 koennecke * Revision 1.1 2007/01/30 03:19:43 koennecke
* - Fixed state monitor eclipse commit problems. Siiiiiiiggggghhhhhh! * - Fixed state monitor eclipse commit problems. Siiiiiiiggggghhhhhh!
* *
@ -87,7 +87,7 @@
*******************************************************************************/ *******************************************************************************/
#ifndef MCSTAS_R_H #ifndef MCSTAS_R_H
#define MCSTAS_R_H "$Revision: 1.1 $" #define MCSTAS_R_H "$Revision$"
#include <math.h> #include <math.h>
#include <string.h> #include <string.h>
@ -569,9 +569,9 @@ void mcsiminfo_close(void);
* *
* Usage: Automatically embbeded in the c code whenever required. * Usage: Automatically embbeded in the c code whenever required.
* *
* $Id: dmcafter.c,v 1.1 2007/01/30 03:19:43 koennecke Exp $ * $Id$
* *
* $Log: dmcafter.c,v $ * $Log$
* Revision 1.1 2007/01/30 03:19:43 koennecke * Revision 1.1 2007/01/30 03:19:43 koennecke
* - Fixed state monitor eclipse commit problems. Siiiiiiiggggghhhhhh! * - Fixed state monitor eclipse commit problems. Siiiiiiiggggghhhhhh!
* *
@ -4356,9 +4356,9 @@ MCNUM mccDet9_zmax;
* %include "read_table-lib" * %include "read_table-lib"
* *
* *
* $Id: dmcafter.c,v 1.1 2007/01/30 03:19:43 koennecke Exp $ * $Id$
* *
* $Log: dmcafter.c,v $ * $Log$
* Revision 1.1 2007/01/30 03:19:43 koennecke * Revision 1.1 2007/01/30 03:19:43 koennecke
* - Fixed state monitor eclipse commit problems. Siiiiiiiggggghhhhhh! * - Fixed state monitor eclipse commit problems. Siiiiiiiggggghhhhhh!
* *
@ -4433,9 +4433,9 @@ static void Table_Stat(t_Table *mc_rt_Table);
* Usage: within SHARE * Usage: within SHARE
* %include "read_table-lib" * %include "read_table-lib"
* *
* $Id: dmcafter.c,v 1.1 2007/01/30 03:19:43 koennecke Exp $ * $Id$
* *
* $Log: dmcafter.c,v $ * $Log$
* Revision 1.1 2007/01/30 03:19:43 koennecke * Revision 1.1 2007/01/30 03:19:43 koennecke
* - Fixed state monitor eclipse commit problems. Siiiiiiiggggghhhhhh! * - Fixed state monitor eclipse commit problems. Siiiiiiiggggghhhhhh!
* *
@ -5284,9 +5284,9 @@ long Virtual_input_Read_Input(char *aFile, char *aType, t_Table *aTable, long *a
* Usage: within SHARE * Usage: within SHARE
* %include "monitor_nd-lib" * %include "monitor_nd-lib"
* *
* $Id: dmcafter.c,v 1.1 2007/01/30 03:19:43 koennecke Exp $ * $Id$
* *
* $Log: dmcafter.c,v $ * $Log$
* Revision 1.1 2007/01/30 03:19:43 koennecke * Revision 1.1 2007/01/30 03:19:43 koennecke
* - Fixed state monitor eclipse commit problems. Siiiiiiiggggghhhhhh! * - Fixed state monitor eclipse commit problems. Siiiiiiiggggghhhhhh!
* *
@ -5460,9 +5460,9 @@ void Monitor_nD_McDisplay(MonitornD_Defines_type *,
* Usage: within SHARE * Usage: within SHARE
* %include "monitor_nd-lib" * %include "monitor_nd-lib"
* *
* $Id: dmcafter.c,v 1.1 2007/01/30 03:19:43 koennecke Exp $ * $Id$
* *
* $Log: dmcafter.c,v $ * $Log$
* Revision 1.1 2007/01/30 03:19:43 koennecke * Revision 1.1 2007/01/30 03:19:43 koennecke
* - Fixed state monitor eclipse commit problems. Siiiiiiiggggghhhhhh! * - Fixed state monitor eclipse commit problems. Siiiiiiiggggghhhhhh!
* *

View File

@ -14,6 +14,7 @@
#define MOTREDO -1 #define MOTREDO -1
#define MOTFAIL 0 #define MOTFAIL 0
#define MOTOK 1 #define MOTOK 1
#define TEXTPARLEN 1024
typedef struct __AbstractMoDriv { typedef struct __AbstractMoDriv {
/* general motor driver interface /* general motor driver interface
@ -33,6 +34,7 @@ typedef struct __AbstractMoDriv {
char *name, float newValue); char *name, float newValue);
void (*ListDriverPar) (void *self, char *motorName, SConnection * pCon); void (*ListDriverPar) (void *self, char *motorName, SConnection * pCon);
void (*KillPrivate) (void *self); void (*KillPrivate) (void *self);
int (*GetDriverTextPar) (void *self, char *name, char *textPar);
} MotorDriver; } MotorDriver;
/* the first fields above HAVE to be IDENTICAL to those below */ /* the first fields above HAVE to be IDENTICAL to those below */
@ -56,6 +58,7 @@ typedef struct ___MoSDriv {
char *name, float newValue); char *name, float newValue);
void (*ListDriverPar) (void *self, char *motorName, SConnection * pCon); void (*ListDriverPar) (void *self, char *motorName, SConnection * pCon);
void (*KillPrivate) (void *self); void (*KillPrivate) (void *self);
int (*GetDriverTextPar) (void *self, char *name, char *textPar);
/* Simulation specific fields */ /* Simulation specific fields */
float fFailure; /* percent random failures */ float fFailure; /* percent random failures */

47
motor.c
View File

@ -81,6 +81,8 @@
#define IGNOREFAULT 10 #define IGNOREFAULT 10
#define MOVECOUNT 11 #define MOVECOUNT 11
extern double DoubleTime(void);
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
static void SetMotorError(pMotor self, char *text) static void SetMotorError(pMotor self, char *text)
{ {
@ -351,8 +353,9 @@ static int checkPosition(pMotor self, SConnection * pCon)
SCWrite(pCon, pBueffel, eWarning); SCWrite(pCon, pBueffel, eWarning);
return HWFault; return HWFault;
} }
snprintf(pBueffel, 131, "WARNING: %s off position by %f", snprintf(pBueffel, 131, "WARNING: %s off position by %f%s",
self->name, absf(fHard - self->fTarget)); self->name, absf(fHard - self->fTarget),
self->fTarget > fHard ? "-" : "");
SCWrite(pCon, pBueffel, eLog); SCWrite(pCon, pBueffel, eLog);
status = statusRunTo(self, pCon); status = statusRunTo(self, pCon);
return status; return status;
@ -361,16 +364,19 @@ static int checkPosition(pMotor self, SConnection * pCon)
} }
/*--------------------------------------------------------------------*/ /*--------------------------------------------------------------------*/
static void finishDriving(pMotor self, SConnection * pCon) void finishDriving(pMotor self, SConnection * pCon)
{ {
MotCallback sCall; MotCallback sCall;
MotorGetSoftPosition(self, pCon, &sCall.fVal); MotorGetSoftPosition(self, pCon, &sCall.fVal);
sCall.pName = self->name; sCall.pName = self->name;
self->fPosition = sCall.fVal; self->fPosition = sCall.fVal;
self->fPosition = sCall.fVal; self->fPosition = sCall.fVal;
InvokeCallBack(self->pCall, MOTDRIVE, &sCall); /* send also very last position */ if (self->moving) {
InvokeCallBack(self->pCall, MOTEND, &sCall); InvokeCallBack(self->pCall, MOTDRIVE, &sCall); /* send also very last position */
tracePar(self->name,"%f",sCall.fVal); InvokeCallBack(self->pCall, MOTEND, &sCall);
tracePar(self->name,"%f",sCall.fVal);
}
self->moving = 0;
self->running = 0; self->running = 0;
} }
@ -474,13 +480,15 @@ static void handleMoveCallback(pMotor self, SConnection * pCon)
{ {
MotCallback sCall; MotCallback sCall;
self->posCount++; double current_time, skip_time;
if (self->posCount >= ObVal(self->ParArray, MOVECOUNT)) { current_time = DoubleTime();
skip_time = 0.001 * ObVal(self->ParArray,MOVECOUNT);
if(self->last_report_time + skip_time <= current_time) {
MotorGetSoftPosition(self, pCon, &sCall.fVal); MotorGetSoftPosition(self, pCon, &sCall.fVal);
sCall.pName = self->name; sCall.pName = self->name;
InvokeCallBack(self->pCall, MOTDRIVE, &sCall); InvokeCallBack(self->pCall, MOTDRIVE, &sCall);
tracePar(self->name,"%f",sCall.fVal); tracePar(self->name,"%f",sCall.fVal);
self->posCount = 0; self->last_report_time = current_time;
} }
} }
@ -749,8 +757,10 @@ static long MotorRunImpl(void *sulf, SConnection * pCon, float fNew)
self->posFaultCount = 0; self->posFaultCount = 0;
self->retryCount = 0; self->retryCount = 0;
self->stopped = 0; self->stopped = 0;
self->moving = 1;
self->fTarget = fHard; self->fTarget = fHard;
InvokeCallBack(self->pCall, HDBVAL, self); InvokeCallBack(self->pCall, HDBVAL, self);
self->last_report_time = 0.0;
self->posCount = 0; self->posCount = 0;
iRet = self->pDriver->RunTo(self->pDriver, fHard); iRet = self->pDriver->RunTo(self->pDriver, fHard);
if (iRet != OKOK) { /* try three times to fix it */ if (iRet != OKOK) { /* try three times to fix it */
@ -824,7 +834,7 @@ pMotor MotorInit(char *drivername, char *name, MotorDriver * pDriv)
ObParInit(pM->ParArray, ECOUNT, "failafter", 3.0, usMugger); ObParInit(pM->ParArray, ECOUNT, "failafter", 3.0, usMugger);
ObParInit(pM->ParArray, POSCOUNT, "maxretry", 3.0, usMugger); ObParInit(pM->ParArray, POSCOUNT, "maxretry", 3.0, usMugger);
ObParInit(pM->ParArray, IGNOREFAULT, "ignorefault", 0.0, usMugger); ObParInit(pM->ParArray, IGNOREFAULT, "ignorefault", 0.0, usMugger);
ObParInit(pM->ParArray, MOVECOUNT, "movecount", 10.0, usMugger); ObParInit(pM->ParArray, MOVECOUNT, "movecount", 500.0, usMugger);
pDriv->GetPosition(pDriv, &(pM->fPosition)); pDriv->GetPosition(pDriv, &(pM->fPosition));
pM->fTarget = pM->fPosition; pM->fTarget = pM->fPosition;
pM->endScriptID = 0; pM->endScriptID = 0;
@ -1210,6 +1220,20 @@ static int EndScriptCallback(int iEvent, void *pEvent, void *pUser)
return iRet; return iRet;
} }
/*
* Context test function for callback removal
*/
int CheckMotiMatch(const void* context, const void* pUserData)
{
pMotInfo pMoti = (pMotInfo) pUserData;
SConnection *pCon = (SConnection*) context;
if (VerifyConnection(pCon) && VerifyConnection(pMoti->pCon)) {
if (pMoti->pCon->ident == pCon->ident)
return 0;
}
return 1;
}
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
The wrapper function for a motor. Commands currently supported are: The wrapper function for a motor. Commands currently supported are:
@ -1305,13 +1329,14 @@ int MotorAction(SConnection * pCon, SicsInterp * pSics, void *pData,
} }
pMoti->lastValue = fValue; pMoti->lastValue = fValue;
RemoveCallbackUsr(self->pCall, InterestCallback, CheckMotiMatch, pCon); /* only this one */
lID = RegisterCallback(self->pCall, MOTDRIVE, InterestCallback, lID = RegisterCallback(self->pCall, MOTDRIVE, InterestCallback,
pMoti, KillInfo); pMoti, KillInfo);
DeleteTokenList(pList); DeleteTokenList(pList);
SCSendOK(pCon); SCSendOK(pCon);
return 1; return 1;
} else if (strcmp(pCurrent->text, "uninterest") == 0) { } else if (strcmp(pCurrent->text, "uninterest") == 0) {
RemoveCallbackCon(self->pCall, pCon); RemoveCallbackUsr(self->pCall, InterestCallback, CheckMotiMatch, pCon); /* only this one */
SCSendOK(pCon); SCSendOK(pCon);
DeleteTokenList(pList); DeleteTokenList(pList);
return 1; return 1;

View File

@ -41,6 +41,9 @@ typedef struct __Motor {
int stopReported; int stopReported;
int errorCount; int errorCount;
int running; int running;
int moving;
double last_report_time;
ObjectFunc pActionRoutine;
ObPar *ParArray; ObPar *ParArray;
void *pPrivate; void *pPrivate;
void (*KillPrivate) (void *); void (*KillPrivate) (void *);

View File

@ -298,7 +298,7 @@ static int SecMotorStatus(void *sulf, SConnection * pCon)
int status; int status;
pHdb node = NULL; pHdb node = NULL;
hdbValue v; hdbValue v;
float interrupt; float interrupt = 0.;
char error[132]; char error[132];
assert(sulf); assert(sulf);
@ -350,7 +350,7 @@ static int SecMotorStatus(void *sulf, SConnection * pCon)
case HWFault: case HWFault:
self->posCount = 10000; self->posCount = 10000;
handleMoveCallback(self, pCon); handleMoveCallback(self, pCon);
SecMotorGetPar(self, "interrupt", &interrupt); SecMotorGetPar(self, "interruptmode", &interrupt);
if (SCGetInterrupt(pCon) < (int) interrupt) { if (SCGetInterrupt(pCon) < (int) interrupt) {
SCSetInterrupt(pCon, (int) interrupt); SCSetInterrupt(pCon, (int) interrupt);
} }
@ -527,7 +527,7 @@ static hdbCallbackReturn SecMotorCallback(pHdb node, void *userData,
SCSetInterrupt(pCon, eAbortBatch); SCSetInterrupt(pCon, eAbortBatch);
self->pDrivInt->iErrorCount = 0; self->pDrivInt->iErrorCount = 0;
child = GetHipadabaNode(self->pDescriptor->parNode, "status"); child = GetHipadabaNode(self->pDescriptor->parNode, "status");
UpdateHipadabaPar(child, MakeHdbText("run"), pCon); UpdateHipadabaPar(child, MakeHdbText("error"), pCon);
return hdbAbort; return hdbAbort;
} }

View File

@ -31,6 +31,14 @@
#define MAXSLAVE 16 #define MAXSLAVE 16
#define NOCOUNTERS -2727 #define NOCOUNTERS -2727
/*
checkSlaves codes
*/
#define WAITMASTER 100
#define WAITSLAVE 200
#define FINISHED 300
/*=============== code for the driver ======================================*/ /*=============== code for the driver ======================================*/
typedef struct { typedef struct {
void *slaveData[MAXSLAVE]; void *slaveData[MAXSLAVE];
@ -107,7 +115,7 @@ static int MMCCStart(void *pData, SConnection * pCon)
pCount->isUpToDate = 0; pCount->isUpToDate = 0;
pCount->tStart = time(NULL); pCount->tStart = time(NULL);
InvokeCallBack(pCount->pCall, COUNTSTART, pCon); InvokeCallBack(pCount->pCall, COUNTSTART, pCon);
self->checkSlaves = 0; self->checkSlaves = WAITMASTER;
return OKOK; return OKOK;
} }
@ -115,7 +123,7 @@ static int MMCCStart(void *pData, SConnection * pCon)
static int MMCCStatus(void *pData, SConnection * pCon) static int MMCCStatus(void *pData, SConnection * pCon)
{ {
int status, i; int status = HWIdle, i;
pCounter pCount = NULL, pMaster = NULL;; pCounter pCount = NULL, pMaster = NULL;;
pMultiCounter self = NULL; pMultiCounter self = NULL;
pDummy pDum = NULL; pDummy pDum = NULL;
@ -132,7 +140,7 @@ static int MMCCStatus(void *pData, SConnection * pCon)
return HWFault; return HWFault;
} }
if(self->checkSlaves == 0) { if(self->checkSlaves == WAITMASTER) {
status = self->slaves[0]->CheckCountStatus(self->slaveData[0], pCon); status = self->slaves[0]->CheckCountStatus(self->slaveData[0], pCon);
if (status == HWIdle || status == HWFault) { if (status == HWIdle || status == HWFault) {
/* /*
@ -141,11 +149,11 @@ static int MMCCStatus(void *pData, SConnection * pCon)
*/ */
MMCCHalt(pData); MMCCHalt(pData);
ReleaseCountLock(pCount->pCountInt); ReleaseCountLock(pCount->pCountInt);
self->checkSlaves = 1; self->checkSlaves = WAITSLAVE;
status = HWBusy; status = HWBusy;
} }
pCount->pDriv->fLastCurrent = GetControlValue(self->slaveData[0]); pCount->pDriv->fLastCurrent = GetControlValue(self->slaveData[0]);
} else { } else if(self->checkSlaves == WAITSLAVE) {
/* /*
* wait for the detectors to report finish too. Otherwise, with the second * wait for the detectors to report finish too. Otherwise, with the second
* generation HM data may not be fully transferred. * generation HM data may not be fully transferred.
@ -172,7 +180,9 @@ static int MMCCStatus(void *pData, SConnection * pCon)
} }
status = HWIdle; status = HWIdle;
InvokeCallBack(pCount->pCall, COUNTEND, pCon); InvokeCallBack(pCount->pCall, COUNTEND, pCon);
self->checkSlaves = 0; self->checkSlaves = FINISHED;
} else if(self->checkSlaves == FINISHED){
status = HWIdle;
} }
return status; return status;
} }
@ -530,6 +540,7 @@ int MakeMultiCounter(SConnection * pCon, SicsInterp * pSics,
self->slaveData[self->nSlaves] = pCom->pData; self->slaveData[self->nSlaves] = pCom->pData;
self->nSlaves++; self->nSlaves++;
} }
self->checkSlaves = FINISHED;
/* /*
now install our action command and we are done now install our action command and we are done

2
mumo.c
View File

@ -396,7 +396,7 @@ static int ParseAlias(psParser pParse, SConnection * pCon, pMulMot self)
return 1; return 1;
break; break;
default: default:
snprintf(pBueffel,1024, "ERROR: Unexpected symbol %s", pParse->Token); snprintf(pBueffel,sizeof(pBueffel), "ERROR: Unexpected symbol %s", pParse->Token);
SCWrite(pCon, pBueffel, eError); SCWrite(pCon, pBueffel, eError);
return 0; return 0;
} }

View File

@ -21,10 +21,10 @@
For further information, see <http://www.nexus.anl.gov/> For further information, see <http://www.nexus.anl.gov/>
$Id: napiu.c,v 1.4 2012/03/29 08:41:06 koennecke Exp $ $Id$
----------------------------------------------------------------------------*/ ----------------------------------------------------------------------------*/
static const char* rscid = "$Id: napiu.c,v 1.4 2012/03/29 08:41:06 koennecke Exp $"; /* Revision interted by CVS */ static const char* rscid = "$Id$"; /* Revision interted by CVS */
#include <stdlib.h> #include <stdlib.h>
#include <assert.h> #include <assert.h>

View File

@ -21,7 +21,7 @@
For further information, see <http://www.nexus.anl.gov/> For further information, see <http://www.nexus.anl.gov/>
$Id: napiu.h,v 1.3 2009/02/13 09:00:20 koennecke Exp $ $Id$
----------------------------------------------------------------------------*/ ----------------------------------------------------------------------------*/

View File

@ -188,7 +188,7 @@ mkChannel *NETAccept(mkChannel * self, long timeout)
return NULL; /* eof */ return NULL; /* eof */
} }
iRet = iRet =
uselect((self->sockid + 1), (fd_set *) & lMask, NULL, NULL, &tmo); uselect((self->sockid + 1), &lMask, NULL, NULL, &tmo);
if (iRet <= 0) { if (iRet <= 0) {
/* failure, or no request */ /* failure, or no request */
return NULL; return NULL;
@ -327,7 +327,7 @@ int NETConnectFinished(mkChannel * self)
return -1; return -1;
} }
oldopts = fcntl(self->sockid, F_GETFL, 0); oldopts = fcntl(self->sockid, F_GETFL, 0);
if (!(oldopts | O_NONBLOCK)) { if (!(oldopts & O_NONBLOCK)) { /* DCL was | */
/* assume success when in blocking mode */ /* assume success when in blocking mode */
return 1; return 1;
} }
@ -360,7 +360,7 @@ int NETConnectFinished(mkChannel * self)
} }
/* reset to blocking mode */ /* reset to blocking mode */
olderrno = errno; olderrno = errno;
fcntl(self->sockid, F_SETFL, oldopts | ~O_NONBLOCK); fcntl(self->sockid, F_SETFL, oldopts & ~O_NONBLOCK); /* DCL was | */
errno = olderrno; errno = olderrno;
return iret; return iret;
} }
@ -679,7 +679,7 @@ int NETReadTillTerm(mkChannel * self, long timeout,
status = NETAvailable(self, timeout - dif); status = NETAvailable(self, timeout - dif);
}; };
}; };
return status; return bufPtr;
} }
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
@ -753,14 +753,20 @@ int NETReconnectWithFlags(mkChannel * self, int flags)
if (self->sockid != 0) { if (self->sockid != 0) {
close(self->sockid); close(self->sockid);
} }
/* Reopen and try to get it on the olf fd */ /* Reopen and try to get it on the old fd */
sock = socket(AF_INET, SOCK_STREAM, 0); sock = socket(AF_INET, SOCK_STREAM, 0);
/* If this isn't the same fd, try to move it over */
if (self->sockid != sock) { if (self->sockid != sock) {
/* Duplicate the new socket with the old fd if we can */
iRet = fcntl(sock, F_DUPFD, self->sockid); iRet = fcntl(sock, F_DUPFD, self->sockid);
if (iRet != sock) if (iRet != self->sockid) {
/* If we didn't get the one we want, use original and close new */
self->sockid = sock; self->sockid = sock;
else close(iRet);
} else {
/* If we did get the one we want, close original and use old */
close(sock); close(sock);
}
sock = self->sockid; sock = self->sockid;
} }
/* restore the old flags */ /* restore the old flags */
@ -798,7 +804,7 @@ int NETReconnectWithFlags(mkChannel * self, int flags)
if (iRet <= 0) if (iRet <= 0)
iRet = -1; /* failure */ iRet = -1; /* failure */
} }
if (FD_ISSET(self->sockid, &wmask)) { else if (FD_ISSET(self->sockid, &wmask)) {
iRet = send(self->sockid, NULL, 0, 0); iRet = send(self->sockid, NULL, 0, 0);
if (iRet < 0) if (iRet < 0)
iRet = -1; /* failure */ iRet = -1; /* failure */
@ -920,7 +926,7 @@ mkChannel *UDPConnect(char *name, int port)
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
long UDPRead(mkChannel * self, char *buffer, long lLen, int timeout) long UDPRead(mkChannel * self, char *buffer, long lLen, int timeout)
{ {
long lMask = 0L; fd_set lMask;
struct timeval tmo = { 0, 1 }; struct timeval tmo = { 0, 1 };
long iRet; long iRet;
socklen_t iLang; socklen_t iLang;
@ -934,9 +940,10 @@ long UDPRead(mkChannel * self, char *buffer, long lLen, int timeout)
/* setup for select first */ /* setup for select first */
tmo.tv_usec = (timeout % 1000) * 1000; tmo.tv_usec = (timeout % 1000) * 1000;
tmo.tv_sec = timeout / 1000; tmo.tv_sec = timeout / 1000;
lMask = (1 << self->sockid); FD_ZERO(&lMask);
FD_SET(self->sockid, &lMask);
iRet = iRet =
uselect((self->sockid + 1), (fd_set *) & lMask, NULL, NULL, &tmo); uselect((self->sockid + 1), &lMask, NULL, NULL, &tmo);
if (iRet <= 0) { if (iRet <= 0) {
/* failure, or no data */ /* failure, or no data */
return 0; return 0;

42
nread.c
View File

@ -42,6 +42,8 @@
#include "commandlog.h" #include "commandlog.h"
#include "uselect.h" #include "uselect.h"
#include "trace.h" #include "trace.h"
#include "protocol.h"
extern pServer pServ; extern pServer pServ;
extern int VerifyChannel(mkChannel * self); /* defined in network.c */ extern int VerifyChannel(mkChannel * self); /* defined in network.c */
@ -294,15 +296,25 @@ static int NetReadRead(pNetRead self, pNetItem pItem)
*pEnd = '\0'; *pEnd = '\0';
/* do we have something in hold ? */ /* do we have something in hold ? */
if (strlen(pItem->pHold) > 0) { if (strlen(pItem->pHold) > 0) {
strlcat(pItem->pHold, pPtr,511); strlcat(pItem->pHold, pPtr, 511);
iStat = CostaTop(pItem->pCon->pStack, pItem->pHold); /* DFC locking for protocol zero only */
if (pItem->pCon->iProtocolID == PROTSICS &&
CostaLocked(pItem->pCon->pStack))
iStat = 0;
else
iStat = CostaTop(pItem->pCon->pStack, pItem->pHold);
if (!iStat) { if (!iStat) {
SCWrite(pItem->pCon, "ERROR: Busy", eError); SCWrite(pItem->pCon, "ERROR: Busy", eError);
} }
pItem->pHold[0] = '\0'; pItem->pHold[0] = '\0';
} else { } else {
/* no, normal command */ /* no, normal command */
iStat = CostaTop(pItem->pCon->pStack, pPtr); /* DFC locking for protocol zero only */
if (pItem->pCon->iProtocolID == PROTSICS &&
CostaLocked(pItem->pCon->pStack))
iStat = 0;
else
iStat = CostaTop(pItem->pCon->pStack, pPtr);
if (!iStat) { if (!iStat) {
SCWrite(pItem->pCon, "ERROR: Busy", eError); SCWrite(pItem->pCon, "ERROR: Busy", eError);
} }
@ -487,7 +499,12 @@ static int TelnetRead(pNetRead self, pNetItem pItem)
break; break;
case '\r': case '\r':
case '\n': case '\n':
iStat = CostaTop(pItem->pCon->pStack, pItem->pHold); /* DFC locking for protocol zero only */
if (pItem->pCon->iProtocolID == PROTSICS &&
CostaLocked(pItem->pCon->pStack))
iStat = 0;
else
iStat = CostaTop(pItem->pCon->pStack, pItem->pHold);
/* printf("%s\n",pItem->pHold); */ /* printf("%s\n",pItem->pHold); */
if (!iStat) { if (!iStat) {
SCWrite(pItem->pCon, "ERROR: Busy", eError); SCWrite(pItem->pCon, "ERROR: Busy", eError);
@ -1027,6 +1044,7 @@ static int testAndInvokeInterrupt(pCommandCBData self, int handle)
snprintf(buffer, 512, "INTERRUPT %d issued on sock %d", snprintf(buffer, 512, "INTERRUPT %d issued on sock %d",
iInt, handle); iInt, handle);
WriteToCommandLog("SYS>", buffer); WriteToCommandLog("SYS>", buffer);
SICSLogWrite(buffer, eInternal);
if (iInt == eEndServer) { if (iInt == eEndServer) {
TaskStop(pServ->pTasker); TaskStop(pServ->pTasker);
} }
@ -1060,8 +1078,10 @@ static int CommandDataCB(int handle, void *userData)
if (pPtr[i] == '\r' || pPtr[i] == '\n') { if (pPtr[i] == '\r' || pPtr[i] == '\n') {
self->state = SKIPTERM; self->state = SKIPTERM;
if (!testAndInvokeInterrupt(self, handle)) { if (!testAndInvokeInterrupt(self, handle)) {
status = if (self->pCon->iProtocolID == PROTSICS && CostaLocked(self->pCon->pStack))
CostaTop(self->pCon->pStack, GetCharArray(self->command)); status = 0;
else
status = CostaTop(self->pCon->pStack, GetCharArray(self->command));
if (!status) { if (!status) {
SCWrite(self->pCon, "ERROR: Busy", eError); SCWrite(self->pCon, "ERROR: Busy", eError);
} }
@ -1162,8 +1182,10 @@ static int ANETTelnetProcess(int handle, void *usData)
case '\r': case '\r':
case '\n': case '\n':
if (!testAndInvokeInterrupt(self, handle)) { if (!testAndInvokeInterrupt(self, handle)) {
status = if (self->pCon->iProtocolID == PROTSICS && CostaLocked(self->pCon->pStack))
CostaTop(self->pCon->pStack, GetCharArray(self->command)); status = 0;
else
status = CostaTop(self->pCon->pStack, GetCharArray(self->command));
if (!status) { if (!status) {
SCWrite(self->pCon, "ERROR: Busy", eError); SCWrite(self->pCon, "ERROR: Busy", eError);
} }
@ -1333,8 +1355,8 @@ static int TelnetAcceptCB(int handle, void *userData)
/*------------------------------------------------------------------------------------*/ /*------------------------------------------------------------------------------------*/
static void NREADlog(int level, char *txt, void *userData) static void NREADlog(int level, char *txt, void *userData)
{ {
traceSys("anet",txt); traceSys("anet","%s",txt);
puts(txt); SICSLogWrite(txt, (level == ANETERROR) ? eLogError : eLog);
} }
/*------------------------------------------------------------------------------------*/ /*------------------------------------------------------------------------------------*/

View File

@ -40,12 +40,16 @@
#include "commandlog.h" #include "commandlog.h"
extern void StopExit(void); /* in SICSmain.c */
extern int openDevexecLog(); /* in devexec.c */ extern int openDevexecLog(); /* in devexec.c */
extern void NetWatchInit(void); /* in nwatch.c */ extern int NetWatchTask(void *pData); /* in nwatch.c */
/* ========================= Less dreadful file statics =================== */ /*------------------------------------------------------------------------*/
static void StopExit(void)
{
if (pServ) {
StopServer(pServ);
}
}
#define DEFAULTINIFILE "servo.tcl" #define DEFAULTINIFILE "servo.tcl"
#define DEFAULTSTATUSFILE "sicsstat.tcl" #define DEFAULTSTATUSFILE "sicsstat.tcl"
@ -116,7 +120,7 @@ int InitServer(char *file, pServer * pServ)
pSICSOptions = IFAddOption(pSICSOptions, "ConMask", "0"); pSICSOptions = IFAddOption(pSICSOptions, "ConMask", "0");
/* initialize the network watcher */ /* initialize the network watcher */
NetWatchInit(); TaskRegister(self->pTasker, NetWatchTask, NULL, NULL, NULL, 1);
/* initialise the server from script */ /* initialise the server from script */
SetWriteHistory(0); SetWriteHistory(0);
@ -507,3 +511,23 @@ int ServerIsStarting(pServer self)
{ {
return self->pReader == NULL; return self->pReader == NULL;
} }
pServer pServ = NULL;
/*--------------------------------------------------------------------------*/
SicsInterp *GetInterpreter(void)
{
return pServ->pSics;
}
/*--------------------------------------------------------------------------*/
pExeList GetExecutor(void)
{
return pServ->pExecutor;
}
/*-------------------------------------------------------------------------*/
pTaskMan GetTasker(void)
{
return pServ->pTasker;
}

114
nwatch.c
View File

@ -18,8 +18,8 @@
#include <sys/time.h> #include <sys/time.h>
#include "fortify.h" #include "fortify.h"
#include "nwatch.h" #include "nwatch.h"
#include "sics.h"
#include "uselect.h" #include "uselect.h"
#include "sics.h"
#define NWMAGIC 51966 #define NWMAGIC 51966
@ -36,14 +36,12 @@ typedef struct __netwatcher_s {
/* Singleton pattern */ /* Singleton pattern */
static pNetWatch instance = NULL; static pNetWatch instance = NULL;
static int NetWatchTask(void *pData);
/** /**
* \brief Initialises the Net Watcher singleton and starts the task * \brief Initialises the Net Watcher singleton and starts the task
* *
* \return 1=success, 0=failure * \return 1=success, 0=failure
*/ */
int NetWatchInit(void) static pNetWatch NetWatchGetInstance(void)
{ {
/* /*
* If the singleton has not yet been created, do so now * If the singleton has not yet been created, do so now
@ -54,9 +52,8 @@ int NetWatchInit(void)
return 0; return 0;
memset(instance, 0, sizeof(NetWatch)); memset(instance, 0, sizeof(NetWatch));
instance->lMagic = NWMAGIC; instance->lMagic = NWMAGIC;
TaskRegisterN(pServ->pTasker,"nwatch", NetWatchTask, NULL, NULL, NULL, 1);
} }
return 1; return instance;
} }
/* /*
@ -67,10 +64,13 @@ typedef struct __netwatchtimer {
struct timeval tv; /* time when event is due */ struct timeval tv; /* time when event is due */
pNWCallback func; /* function to call */ pNWCallback func; /* function to call */
void *cntx; /* abstract context to pass to callback */ void *cntx; /* abstract context to pass to callback */
long int tick; /* millisecond repeat rate */ int msec; /* millisecond delay time */
int tick; /* millisecond repeat rate */
long int vrfy; /* integrity check */ long int vrfy; /* integrity check */
} NWTimer; } NWTimer;
static pNWTimer activeTimer = NULL;
/* /*
* \brief private function to insert an entry into the sorted timer queue. * \brief private function to insert an entry into the sorted timer queue.
* *
@ -83,6 +83,7 @@ static int NetWatchTimerInsQue(pNetWatch self, pNWTimer handle)
if (self->tq_head == NULL) { if (self->tq_head == NULL) {
self->tq_head = self->tq_tail = handle; self->tq_head = self->tq_tail = handle;
handle->next = NULL; handle->next = NULL;
handle->vrfy = NWMAGIC;
return 1; return 1;
} }
/* if new one is not earlier than latest one, insert after latest */ /* if new one is not earlier than latest one, insert after latest */
@ -92,6 +93,7 @@ static int NetWatchTimerInsQue(pNetWatch self, pNWTimer handle)
self->tq_tail->next = handle; self->tq_tail->next = handle;
self->tq_tail = handle; self->tq_tail = handle;
handle->next = NULL; handle->next = NULL;
handle->vrfy = NWMAGIC;
return 1; return 1;
} }
/* if new one is not later than earliest one, insert before earliest */ /* if new one is not later than earliest one, insert before earliest */
@ -100,6 +102,7 @@ static int NetWatchTimerInsQue(pNetWatch self, pNWTimer handle)
handle->tv.tv_usec <= self->tq_head->tv.tv_usec)) { handle->tv.tv_usec <= self->tq_head->tv.tv_usec)) {
handle->next = self->tq_head; handle->next = self->tq_head;
self->tq_head = handle; self->tq_head = handle;
handle->vrfy = NWMAGIC;
return 1; return 1;
} else { } else {
/* must be in between two so start at the first entry */ /* must be in between two so start at the first entry */
@ -113,8 +116,10 @@ static int NetWatchTimerInsQue(pNetWatch self, pNWTimer handle)
/* slip new one in between this one and the next one */ /* slip new one in between this one and the next one */
handle->next = pNxt->next; handle->next = pNxt->next;
pNxt->next = handle; pNxt->next = handle;
handle->vrfy = NWMAGIC;
return 1;
} }
return 1; return 0;
} }
/* /*
@ -125,6 +130,7 @@ static int NetWatchTimerInsQue(pNetWatch self, pNWTimer handle)
*/ */
static int NetWatchTimerRemQue(pNetWatch self, pNWTimer handle) static int NetWatchTimerRemQue(pNetWatch self, pNWTimer handle)
{ {
assert(handle->vrfy == NWMAGIC);
/* handle the case of first and possibly only */ /* handle the case of first and possibly only */
if (handle == self->tq_head) { if (handle == self->tq_head) {
self->tq_head = self->tq_head->next; /* may be NULL */ self->tq_head = self->tq_head->next; /* may be NULL */
@ -145,13 +151,15 @@ static int NetWatchTimerRemQue(pNetWatch self, pNWTimer handle)
if (handle == self->tq_tail) if (handle == self->tq_tail)
self->tq_tail = pNxt; self->tq_tail = pNxt;
} }
handle->vrfy = 0;
return 1; return 1;
} }
int NetWatchRegisterTimer(pNWTimer * handle, int mSec, int NetWatchRegisterTimer(pNWTimer * handle, int mSec,
pNWCallback callback, void *context) pNWCallback callback, void *context)
{ {
pNetWatch self = instance; assert(callback);
pNetWatch self = NetWatchGetInstance();
if (!self || self->lMagic != NWMAGIC) if (!self || self->lMagic != NWMAGIC)
return 0; return 0;
pNWTimer pNew = (pNWTimer) malloc(sizeof(NWTimer)); pNWTimer pNew = (pNWTimer) malloc(sizeof(NWTimer));
@ -165,10 +173,10 @@ int NetWatchRegisterTimer(pNWTimer * handle, int mSec,
pNew->tv.tv_sec++; pNew->tv.tv_sec++;
pNew->tv.tv_usec -= 1000000; pNew->tv.tv_usec -= 1000000;
} }
pNew->msec = mSec;
pNew->tick = 0; pNew->tick = 0;
pNew->func = callback; pNew->func = callback;
pNew->cntx = context; pNew->cntx = context;
pNew->vrfy = NWMAGIC;
NetWatchTimerInsQue(self, pNew); NetWatchTimerInsQue(self, pNew);
*handle = pNew; *handle = pNew;
return 1; return 1;
@ -178,6 +186,7 @@ int NetWatchRegisterTimerPeriodic(pNWTimer * handle, int mSecInitial,
int mSecPeriod, pNWCallback callback, int mSecPeriod, pNWCallback callback,
void *context) void *context)
{ {
assert(callback);
if (NetWatchRegisterTimer(handle, mSecInitial, callback, context)) { if (NetWatchRegisterTimer(handle, mSecInitial, callback, context)) {
pNWTimer pNew = *handle; pNWTimer pNew = *handle;
if (pNew == NULL) if (pNew == NULL)
@ -189,16 +198,36 @@ int NetWatchRegisterTimerPeriodic(pNWTimer * handle, int mSecInitial,
return 0; return 0;
} }
pNWTimer NetWatchGetActiveTimer(void)
{
return activeTimer;
}
int NetWatchGetTimerInitial(pNWTimer handle)
{
if (handle == NULL
|| (handle->vrfy != NWMAGIC && handle->vrfy != ~NWMAGIC))
return 0;
return handle->msec;
}
int NetWatchGetTimerDelay(pNWTimer handle)
{
return NetWatchGetTimerInitial(handle);
}
int NetWatchGetTimerPeriod(pNWTimer handle) int NetWatchGetTimerPeriod(pNWTimer handle)
{ {
if (handle == NULL || handle->vrfy != NWMAGIC) if (handle == NULL
|| (handle->vrfy != NWMAGIC && handle->vrfy != ~NWMAGIC))
return 0; return 0;
return handle->tick; return handle->tick;
} }
int NetWatchSetTimerPeriod(pNWTimer handle, int mSecPeriod) int NetWatchSetTimerPeriod(pNWTimer handle, int mSecPeriod)
{ {
if (handle == NULL || handle->vrfy != NWMAGIC) if (handle == NULL
|| (handle->vrfy != NWMAGIC && handle->vrfy != ~NWMAGIC))
return 0; return 0;
handle->tick = mSecPeriod; handle->tick = mSecPeriod;
return 1; return 1;
@ -206,9 +235,11 @@ int NetWatchSetTimerPeriod(pNWTimer handle, int mSecPeriod)
int NetWatchRemoveTimer(pNWTimer handle) int NetWatchRemoveTimer(pNWTimer handle)
{ {
pNetWatch self = instance; pNetWatch self = NetWatchGetInstance();
if (!self || self->lMagic != NWMAGIC) if (!self || self->lMagic != NWMAGIC)
return 0; return 0;
if (handle == NULL || handle->vrfy != NWMAGIC)
return 0;
NetWatchTimerRemQue(self, handle); NetWatchTimerRemQue(self, handle);
handle->vrfy = 0; handle->vrfy = 0;
free(handle); free(handle);
@ -239,35 +270,10 @@ static int NetWatchContextInsQue(pNetWatch self, pNWContext handle)
self->cq_tail->next = handle; self->cq_tail->next = handle;
self->cq_tail = handle; self->cq_tail = handle;
} }
handle->vrfy = NWMAGIC;
return 1; return 1;
} }
/**
* \brief private function to remove entry from unsorted queue
*
* \param self singleton
* \param handle entry to insert
*/
static void NetWatchContextRemQue(pNetWatch self, pNWContext handle)
{
if (handle == self->cq_head) { /* if first */
self->cq_head = self->cq_head->next;
if (handle == self->cq_tail) /* if also last */
self->cq_tail = NULL;
} else {
pNWContext pNxt = self->cq_head;
while (pNxt) {
if (handle == pNxt->next) {
pNxt->next = pNxt->next->next;
break;
}
pNxt = pNxt->next;
}
if (handle == self->cq_tail) /* if last */
self->cq_tail = pNxt;
}
return;
}
/** /**
* \brief private function to purge invalid entries * \brief private function to purge invalid entries
@ -286,19 +292,19 @@ static void NetWatchContextPrgQue(pNetWatch self)
free(tmp); free(tmp);
} }
pNxt = self->cq_head; pNxt = self->cq_head;
while (pNxt) { while (pNxt && pNxt->next) {
if (pNxt->next && pNxt->next->sock < 0) { if (pNxt->next->sock < 0) {
pNWContext tmp = NULL; pNWContext tmp = NULL;
tmp = pNxt->next; tmp = pNxt->next;
pNxt->next = pNxt->next->next; pNxt->next = pNxt->next->next;
tmp->vrfy = 0; tmp->vrfy = 0;
free(tmp); free(tmp);
continue;
} }
pNxt = pNxt->next; pNxt = pNxt->next;
} }
/* if the queue is empty clear the tail */ /* if the queue is empty then pNxt is NULL else pNxt points to the tail */
if (self->cq_head == NULL) self->cq_tail = pNxt;
self->cq_tail = pNxt;
self->nInvalid = 0; self->nInvalid = 0;
return; return;
} }
@ -306,8 +312,9 @@ static void NetWatchContextPrgQue(pNetWatch self)
int NetWatchRegisterCallback(pNWContext * handle, int iSocket, int NetWatchRegisterCallback(pNWContext * handle, int iSocket,
pNWCallback callback, void *context) pNWCallback callback, void *context)
{ {
assert(callback);
pNWContext pNew = NULL; pNWContext pNew = NULL;
pNetWatch self = instance; pNetWatch self = NetWatchGetInstance();
if (!self || self->lMagic != NWMAGIC) if (!self || self->lMagic != NWMAGIC)
return 0; return 0;
if (iSocket < 0 || iSocket > 65535) if (iSocket < 0 || iSocket > 65535)
@ -320,7 +327,6 @@ int NetWatchRegisterCallback(pNWContext * handle, int iSocket,
pNew->mode = nwatch_read; pNew->mode = nwatch_read;
pNew->func = callback; pNew->func = callback;
pNew->cntx = context; pNew->cntx = context;
pNew->vrfy = NWMAGIC;
*handle = pNew; *handle = pNew;
NetWatchContextInsQue(self, pNew); NetWatchContextInsQue(self, pNew);
return 1; return 1;
@ -328,13 +334,16 @@ int NetWatchRegisterCallback(pNWContext * handle, int iSocket,
int NetWatchRemoveCallback(pNWContext handle) int NetWatchRemoveCallback(pNWContext handle)
{ {
pNetWatch self = instance; pNetWatch self = NetWatchGetInstance();
if (handle == NULL || handle->vrfy != NWMAGIC) if (handle == NULL || handle->vrfy != NWMAGIC)
return 0; return 0;
if (!self || self->lMagic != NWMAGIC) if (!self || self->lMagic != NWMAGIC)
return 0; return 0;
/* mark as invalid */
handle->sock = -1; handle->sock = -1;
/* increment count of invalid */
self->nInvalid++; self->nInvalid++;
/* leave for garbage collection */
return 1; return 1;
} }
@ -354,7 +363,8 @@ int NetWatchSetMode(pNWContext handle, int mode)
} }
/** /**
* \brief the registered SICS Task to drive all this * \brief the task to drive all this
* Should be called periodically
*/ */
int NetWatchTask(void *pData) int NetWatchTask(void *pData)
{ {
@ -367,7 +377,7 @@ int NetWatchTask(void *pData)
int iCount; int iCount;
/* Check the singleton */ /* Check the singleton */
self = (pNetWatch) instance; self = NetWatchGetInstance();
if (!self || self->lMagic != NWMAGIC) if (!self || self->lMagic != NWMAGIC)
return 0; return 0;
@ -375,7 +385,7 @@ int NetWatchTask(void *pData)
if (self->nInvalid > 0) if (self->nInvalid > 0)
NetWatchContextPrgQue(self); NetWatchContextPrgQue(self);
/* build the select mask */ /* build the select mask */
FD_ZERO(&rMask); FD_ZERO(&rMask);
FD_ZERO(&wMask); FD_ZERO(&wMask);
pNWC = self->cq_head; pNWC = self->cq_head;
@ -430,7 +440,11 @@ int NetWatchTask(void *pData)
break; break;
} }
NetWatchTimerRemQue(self, pNew); NetWatchTimerRemQue(self, pNew);
activeTimer = pNew;
activeTimer->vrfy = ~NWMAGIC;
iStatus = pNew->func(pNew->cntx, 0); iStatus = pNew->func(pNew->cntx, 0);
activeTimer->vrfy = 0;
activeTimer = NULL;
/* /*
* If this is a recurrent timer and the function * If this is a recurrent timer and the function
* indicates to keep it going, put it back in * indicates to keep it going, put it back in

View File

@ -1,5 +1,5 @@
/* /*
* N E T W A T C H E R * N E T W A T C H
* *
* This module watches network connections for sockets becoming readable or * This module watches network connections for sockets becoming readable or
* writeable and invokes callbacks. It also provides a timer mechanism. * writeable and invokes callbacks. It also provides a timer mechanism.
@ -7,8 +7,8 @@
* Douglas Clowes, February 2007 * Douglas Clowes, February 2007
* *
*/ */
#ifndef SICSNETWATCHER #ifndef NETWATCH_H
#define SICSNETWATCHER #define NETWATCH_H
#define nwatch_read 1 #define nwatch_read 1
#define nwatch_write 2 #define nwatch_write 2
@ -53,6 +53,10 @@ int NetWatchRegisterTimerPeriodic(pNWTimer * handle, int mSecInitial,
int mSecPeriod, pNWCallback callback, int mSecPeriod, pNWCallback callback,
void *context); void *context);
pNWTimer NetWatchGetActiveTimer(void);
int NetWatchGetTimerDelay(pNWTimer handle);
int NetWatchGetTimerInitial(pNWTimer handle);
int NetWatchGetTimerPeriod(pNWTimer handle); int NetWatchGetTimerPeriod(pNWTimer handle);
int NetWatchSetTimerPeriod(pNWTimer handle, int mSecPeriod); int NetWatchSetTimerPeriod(pNWTimer handle, int mSecPeriod);
/** /**
@ -103,4 +107,4 @@ int NetWatchGetMode(pNWContext handle);
*/ */
int NetWatchSetMode(pNWContext handle, int mode); int NetWatchSetMode(pNWContext handle, int mode);
#endif /* SICSNETWATCHER */ #endif /* NETWATCH_H */

126
nxdict.c
View File

@ -173,9 +173,9 @@ static void NXDIParse(char *pBuffer, pStringDict pDict)
char *pPtr; char *pPtr;
int iToken; int iToken;
int iMode; int iMode;
char pAlias[132]; char pAlias[1024];
char pDefinition[1024]; /* this is > 10 lines of definition */ char pDefinition[8192]; /* this is > 10 lines of definition */
char pWord[132]; char pWord[1024];
assert(pBuffer); assert(pBuffer);
assert(pDict); assert(pDict);
@ -1490,6 +1490,126 @@ NXstatus NXDinfoalias(NXhandle hFil, NXdict dict, char *pAlias, int *rank,
return iRet; return iRet;
} }
/*------------------------------------------------------------------------*/
NXstatus NXDdefnamedlink(NXhandle hFil, NXdict dict,
char *pTarget, char *pVictim, char *newname)
{
NXdict pDict;
ParDat pParseT, pParseV;
int iRet, i, iStat;
NXlink sLink;
pDict = NXDIAssert(dict);
#ifdef DEFDEBUG
printf("Linking: %s\n", pVictim);
printf("To: %s\n", pTarget);
#endif
/* parse Victim */
pParseV.iMayCreate = 0;
pParseV.pPtr = pVictim;
pParseV.iDepth = 0;
iRet = NXDIDefParse(hFil, pDict, &pParseV);
if (iRet == NX_ERROR) {
/* unwind and throw up */
NXDIUnwind(hFil, pParseV.iDepth);
return NX_ERROR;
}
/* get link data */
if (pParseV.iTerminal == TERMSDS) {
NXgetdataID(hFil, &sLink);
iRet = NXclosedata(hFil);
if (iRet != NX_OK) {
/* unwind and throw up */
NXDIUnwind(hFil, pParseV.iDepth);
return NX_ERROR;
}
} else if (pParseV.iTerminal == TERMVG) {
NXgetgroupID(hFil, &sLink);
} else {
assert(0); /* serious programming error */
}
/* Unwind */
iRet = NXDIUnwind(hFil, pParseV.iDepth);
if (iRet != NX_OK) {
return NX_ERROR;
}
/* parse Target */
pParseT.iMayCreate = 1;
pParseT.pPtr = pTarget;
pParseT.iDepth = 0;
iRet = NXDIDefParse(hFil, pDict, &pParseT);
if (iRet == NX_ERROR) {
/* unwind and throw up */
NXDIUnwind(hFil, pParseT.iDepth);
return NX_ERROR;
}
/* check it being a vGroup! */
if (pParseT.iTerminal != TERMVG) {
NXReportError("ERROR: can link only into a vGroup");
NXDIUnwind(hFil, pParseT.iDepth);
return NX_ERROR;
}
/* link, finally */
iRet = NXmakenamedlink(hFil, newname, &sLink);
/* Unwind anyway */
iStat = NXDIUnwind(hFil, pParseT.iDepth);
if (iStat != NX_OK) {
return NX_ERROR;
}
return iStat;
}
/*--------------------------------------------------------------------------*/
NXstatus NXDaliasnamedlink(NXhandle hFil, NXdict dict,
char *pTarget, char *pVictim, char *newname)
{
char pTargetDef[2048], pVictimDef[2048];
int iRet;
NXdict pDict;
pDynString pRep1 = NULL, pRep2 = NULL;
pDict = NXDIAssert(dict);
/* get Target Definition String */
iRet = NXDget(pDict, pTarget, pTargetDef, 2047);
if (iRet != NX_OK) {
sprintf(pTargetDef, "ERROR: alias %s not recognized", pTarget);
NXReportError(pTargetDef);
return NX_ERROR;
}
/* get Victim definition string */
iRet = NXDget(pDict, pVictim, pVictimDef, 2047);
if (iRet != NX_OK) {
sprintf(pTargetDef, "ERROR: alias %s not recognized", pTarget);
NXReportError(pTargetDef);
return NX_ERROR;
}
/* do replacements */
pRep1 = NXDItextreplace(dict, pTargetDef);
pRep2 = NXDItextreplace(dict, pVictimDef);
if ((!pRep1) || (!pRep2)) {
if (pRep1)
DeleteDynString(pRep1);
if (pRep2)
DeleteDynString(pRep2);
return NX_ERROR;
}
/* call NXdeflin */
iRet = NXDdefnamedlink(hFil, pDict, GetCharArray(pRep1), GetCharArray(pRep2), newname);
DeleteDynString(pRep1);
DeleteDynString(pRep2);
return iRet;
}
/*------------------------------------------------------------------------*/ /*------------------------------------------------------------------------*/
NXstatus NXDdeflink(NXhandle hFil, NXdict dict, NXstatus NXDdeflink(NXhandle hFil, NXdict dict,
char *pTarget, char *pVictim) char *pTarget, char *pVictim)

View File

@ -462,6 +462,7 @@ static void putHdb(SConnection * pCon, SicsInterp * pSics, pNXScript self,
hdbValue v; hdbValue v;
float fVal, *floatAr = NULL; float fVal, *floatAr = NULL;
int i; int i;
int start[5], size[5];
if (argc < 3) { if (argc < 3) {
SCWrite(pCon, "ERROR: putHdb needs at least node name", eLogError); SCWrite(pCon, "ERROR: putHdb needs at least node name", eLogError);
@ -484,6 +485,23 @@ static void putHdb(SConnection * pCon, SicsInterp * pSics, pNXScript self,
} }
} }
GetHipadabaPar(node, &v, pCon); GetHipadabaPar(node, &v, pCon);
if (argc > 3 && strcmp(argv[3], "point") == 0) {
NXDopenalias(self->fileHandle, self->dictHandle, alias);
start[0] = atoi(argv[4]);
size[0] = 1;
switch (v.dataType) {
case HIPINT:
NXputslab(self->fileHandle, &v.v.intValue, start, size);
break;
case HIPFLOAT:
fVal = v.v.doubleValue;
NXputslab(self->fileHandle, &fVal, start, size);
break;
}
ReleaseHdbValue(&v);
NXopenpath(self->fileHandle, "/");
return;
}
switch (v.dataType) { switch (v.dataType) {
case HIPNONE: case HIPNONE:
return; return;
@ -922,6 +940,7 @@ static void putHistogramMemoryChunked(SConnection * pCon,
} }
/*----------------------------------------------------------------------*/ /*----------------------------------------------------------------------*/
#define HANUM 3
static void putSlab(SConnection * pCon, SicsInterp * pSics, pNXScript self, static void putSlab(SConnection * pCon, SicsInterp * pSics, pNXScript self,
int argc, char *argv[]) int argc, char *argv[])
{ {
@ -1986,6 +2005,35 @@ static void makeLink(SConnection * pCon, SicsInterp * pSics,
SCSendOK(pCon); SCSendOK(pCon);
} }
/*------------------------------------------------------------------------*/
extern NXstatus NXDaliasnamedlink(NXhandle hFil, NXdict dict,
char *pTarget, char *pVictim, char *newname);
/*----------------------------------------------------------------------*/
static void makeNamedLink(SConnection * pCon, SicsInterp * pSics,
pNXScript self, int argc, char *argv[])
{
int status;
char pBueffel[256];
if (argc < 5) {
SCWrite(pCon, "ERROR: insufficient number of arguments to makenamedlink",
eLogError);
return;
}
status = NXDaliasnamedlink(self->fileHandle, self->dictHandle,
argv[2], argv[3], argv[4]);
if (status != NX_OK) {
snprintf(pBueffel, 255, "ERROR: linking %s against %s as %s failed",
argv[2], argv[3], argv[4]);
SCWrite(pCon, pBueffel, eLogError);
return;
}
SCSendOK(pCon);
}
/*----------------------------------------------------------------------*/ /*----------------------------------------------------------------------*/
static void updateDictVar(SConnection * pCon, pNXScript self, int argc, static void updateDictVar(SConnection * pCon, pNXScript self, int argc,
char *argv[]) char *argv[])
@ -2095,6 +2143,10 @@ int NXScriptAction(SConnection * pCon, SicsInterp * pSics, void *pData,
makeLink(pCon, pSics, self, argc, argv); makeLink(pCon, pSics, self, argc, argv);
return 1; return 1;
} }
if (strcmp(argv[1], "makenamedlink") == 0) {
makeNamedLink(pCon, pSics, self, argc, argv);
return 1;
}
return 1; return 1;
} }

View File

@ -176,7 +176,9 @@ int ObParSet(ObPar * self, char *obname, char *name, float fVal,
/* are we running? */ /* are we running? */
if(DevExecLevelRunning(pServ->pExecutor, RUNDRIVE)){ if(DevExecLevelRunning(pServ->pExecutor, RUNDRIVE)){
snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: Cannot change parameter while running"); snprintf(pBueffel,sizeof(pBueffel)-1,
"ERROR: Cannot change %s.%s parameter while running",
obname, name);
SCWrite(pCon, pBueffel, eError); SCWrite(pCon, pBueffel, eError);
return 0; return 0;
} }

9
ofac.c
View File

@ -16,8 +16,11 @@
#include "statusfile.h" #include "statusfile.h"
#include "site.h" #include "site.h"
#include "sicshipadaba.h" #include "sicshipadaba.h"
#include "sicsglobal.h"
static unsigned int killStartupCommands = 1; static unsigned int killStartupCommands = 1;
int isDuringInitialization;
extern void DevExecInit(void); /* devexec.c */ extern void DevExecInit(void); /* devexec.c */
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
@ -93,6 +96,8 @@ static void InitIniCommands(SicsInterp * pInter)
PCMD("InternEval", InternalFileEval); PCMD("InternEval", InternalFileEval);
PCMD("kill_command", SICSKill); PCMD("kill_command", SICSKill);
PCMD("list", SicsList); PCMD("list", SicsList);
PCMD("MakeAsyncProtocol", AsyncProtocolFactory);
PCMD("MakeAsyncQueue", AsyncQueueFactory);
PCMD("MakeMcStasController", McStasControllerFactory); PCMD("MakeMcStasController", McStasControllerFactory);
PCMD("MakeMulti", MakeMulti); PCMD("MakeMulti", MakeMulti);
PCMD("MakeOptimise", MakeOptimiser); PCMD("MakeOptimise", MakeOptimiser);
@ -107,6 +112,7 @@ static void InitIniCommands(SicsInterp * pInter)
PCMD("sicscron", MakeCron); PCMD("sicscron", MakeCron);
PCMD("sicsdatafactory", SICSDataFactory); PCMD("sicsdatafactory", SICSDataFactory);
PCMD("sicsdescriptor", SICSDescriptor); PCMD("sicsdescriptor", SICSDescriptor);
PCMD("SICSLog", LogOutput);
PCMD("sicsprompt", SicsPrompt); PCMD("sicsprompt", SicsPrompt);
PCMD("SICSStatus", SICSStatus); PCMD("SICSStatus", SICSStatus);
PCMD("sicstime", SICSTime); PCMD("sicstime", SICSTime);
@ -126,8 +132,6 @@ static void InitIniCommands(SicsInterp * pInter)
SCMD("AntiCollisionInstall", AntiColliderFactory); SCMD("AntiCollisionInstall", AntiColliderFactory);
SCMD("ChopperAdapter", CHAdapterFactory); SCMD("ChopperAdapter", CHAdapterFactory);
SCMD("InstallSinfox", InstallSinfox); SCMD("InstallSinfox", InstallSinfox);
SCMD("MakeAsyncProtocol", AsyncProtocolFactory);
SCMD("MakeAsyncQueue", AsyncQueueFactory);
SCMD("MakeBatchManager", MakeExeManager); SCMD("MakeBatchManager", MakeExeManager);
SCMD("MakeChopper", ChocoFactory); SCMD("MakeChopper", ChocoFactory);
SCMD("MakeCone", MakeCone); SCMD("MakeCone", MakeCone);
@ -240,6 +244,7 @@ int InitObjectCommands(pServer pServ, char *file)
if(killStartupCommands){ if(killStartupCommands){
RemoveStartupCommands(); RemoveStartupCommands();
} }
isDuringInitialization = 0;
return 1; return 1;
} }
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/

View File

@ -32,6 +32,10 @@ typedef struct __Protocol {
int isDefaultSet; int isDefaultSet;
char *pProList[PROLISTLEN]; /* list of valid protocols? */ char *pProList[PROLISTLEN]; /* list of valid protocols? */
} Protocol; } Protocol;
/*================================================================================================
WARNING: These two char arrays may replicate things defined elsewhere. They may be out of
sync with the rest of SIS. Keep in mind.....
==================================================================================================*/
char *pEventType[] = { char *pEventType[] = {
"VALUECHANGE", /* 0 */ "VALUECHANGE", /* 0 */
@ -145,12 +149,11 @@ void DeleteProtocol(void *self)
if (pOld->version) { if (pOld->version) {
free(pOld->version); free(pOld->version);
} }
if (pOld->pProList) {
i = 0; i = 0;
while (NULL != pOld->pProList[i]) { while (NULL != pOld->pProList[i]) {
free(pOld->pProList[i]); free(pOld->pProList[i]);
i++; i++;
}
} }
free(pOld); free(pOld);
} }
@ -171,7 +174,7 @@ static int ContextDo(SConnection * pCon, SicsInterp * pSics, void *pData,
comCon = SCCopyConnection(pCon); comCon = SCCopyConnection(pCon);
if (comCon == NULL) { if (comCon == NULL) {
SCWrite(pCon, "EROOR: out of memory in contextdo", eError); SCWrite(pCon, "ERROR: out of memory in contextdo", eError);
return 0; return 0;
} }
status = Tcl_GetInt(pSics->pTcl, argv[1], &comCon->transID); status = Tcl_GetInt(pSics->pTcl, argv[1], &comCon->transID);
@ -188,7 +191,13 @@ static int ContextDo(SConnection * pCon, SicsInterp * pSics, void *pData,
SCWrite(pCon, "ERROR: no more memory", eError); SCWrite(pCon, "ERROR: no more memory", eError);
return 0; return 0;
} }
if(comCon->transID > 100000) {
SCPrintf(comCon,eLog,"COMSTART %d", comCon->transID);
}
status = InterpExecute(pSics, comCon, command); status = InterpExecute(pSics, comCon, command);
if(comCon->transID > 100000) {
SCPrintf(comCon,eLog,"COMEND %d", comCon->transID);
}
if (command != buffer) if (command != buffer)
free(command); free(command);
SCDeleteConnection(comCon); SCDeleteConnection(comCon);
@ -271,29 +280,29 @@ static int ProtocolSet(SConnection * pCon, Protocol * pPro, char *pProName)
return 0; return 0;
break; break;
case 1: /* normal (connection start default) */ case PROTNORM: /* normal (connection start default) */
SCSetWriteFunc(pMaster, SCNormalWrite); SCSetWriteFunc(pMaster, SCNormalWrite);
SCSetWriteFunc(pCon, SCNormalWrite); SCSetWriteFunc(pCon, SCNormalWrite);
break; break;
case 2: /* outcodes */ case PROTCODE: /* outcodes */
SCSetWriteFunc(pMaster, SCWriteWithOutcode); SCSetWriteFunc(pMaster, SCWriteWithOutcode);
SCSetWriteFunc(pCon, SCWriteWithOutcode); SCSetWriteFunc(pCon, SCWriteWithOutcode);
break; break;
case 3: /* json */ case PROTJSON: /* json */
SCSetWriteFunc(pCon, SCWriteJSON_String); SCSetWriteFunc(pCon, SCWriteJSON_String);
SCSetWriteFunc(pMaster, SCWriteJSON_String); SCSetWriteFunc(pMaster, SCWriteJSON_String);
break; break;
case 4: /* ACT */ case PROTACT: /* ACT */
SCSetWriteFunc(pMaster, SCACTWrite); SCSetWriteFunc(pMaster, SCACTWrite);
SCSetWriteFunc(pCon, SCACTWrite); SCSetWriteFunc(pCon, SCACTWrite);
break; break;
case 5: case PROTALL:
SCSetWriteFunc(pMaster, SCAllWrite); SCSetWriteFunc(pMaster, SCAllWrite);
SCSetWriteFunc(pCon, SCAllWrite); SCSetWriteFunc(pCon, SCAllWrite);
break; break;
case 0: /* default = psi_sics */ case PROTSICS: /* default = psi_sics */
default: default:
SCSetWriteFunc(pMaster, pPro->defaultWriter); SCSetWriteFunc(pMaster, pPro->defaultWriter);
SCSetWriteFunc(pCon, pPro->defaultWriter); SCSetWriteFunc(pCon, pPro->defaultWriter);
@ -332,11 +341,11 @@ int ProtocolGet(SConnection * pCon, void *pData, char *pProName, int len)
/* check list of protocols for valid name */ /* check list of protocols for valid name */
switch (Index) { switch (Index) {
case 0: /* default = psi_sics */ case PROTSICS: /* default = psi_sics */
case 1: /* normal (connection start default) */ case PROTNORM: /* normal (connection start default) */
case 2: /* outcodes */ case PROTCODE: /* outcodes */
case 3: /* json */ case PROTJSON: /* json */
case 4: /* act */ case PROTACT: /* act */
pProName = pPro->pProList[Index]; pProName = pPro->pProList[Index];
return 1; return 1;
break; break;
@ -441,7 +450,7 @@ static int InitDefaultProtocol(SConnection * pCon, Protocol * pPro)
if (0 == pPro->isDefaultSet) { if (0 == pPro->isDefaultSet) {
pPro->defaultWriter = SCGetWriteFunc(pCon); pPro->defaultWriter = SCGetWriteFunc(pCon);
pPro->isDefaultSet = 1; pPro->isDefaultSet = 1;
pCon->iProtocolID = 0; pCon->iProtocolID = PROTSICS;
} }
return pPro->isDefaultSet; return pPro->isDefaultSet;
} }
@ -628,10 +637,11 @@ char *GetProtocolName(SConnection * pCon)
/* check list of protocols for valid name */ /* check list of protocols for valid name */
switch (pCon->iProtocolID) { switch (pCon->iProtocolID) {
case 0: /* default = psi_sics */ case PROTSICS: /* default = psi_sics */
case 1: /* normal (connection start default) */ case PROTNORM: /* normal (connection start default) */
case 2: /* outcodes */ case PROTCODE: /* outcodes */
case 3: /* json */ case PROTJSON: /* json */
case PROTACT: /* act */
return strdup(pPro->pProList[pCon->iProtocolID]); return strdup(pPro->pProList[pCon->iProtocolID]);
break; break;
default: default:
@ -654,13 +664,13 @@ writeFunc GetProtocolWriteFunc(SConnection * pCon)
{ {
if (pCon != NULL) { if (pCon != NULL) {
switch (pCon->iProtocolID) { switch (pCon->iProtocolID) {
case 2: /* outcodes */ case PROTCODE: /* outcodes */
return SCWriteWithOutcode; return SCWriteWithOutcode;
break; break;
case 3: /* json */ case PROTJSON: /* json */
return SCWriteJSON_String; return SCWriteJSON_String;
break; break;
case 4: case PROTACT:
return SCACTWrite; return SCACTWrite;
break; break;
default: default:

View File

@ -15,6 +15,14 @@ static char *pProTags[3] = {
#define esStart -1 #define esStart -1
#define esFinish -2 #define esFinish -2
/*---------------------- protocol defines -------------------------------*/
#define PROTSICS 0
#define PROTNORM 1
#define PROTCODE 2
#define PROTJSON 3
#define PROTACT 4
#define PROTALL 5
/*--------------------- lifecycle -------------------------------------- */ /*--------------------- lifecycle -------------------------------------- */
int InstallProtocol(SConnection * pCon, SicsInterp * pSics, void *pData, int InstallProtocol(SConnection * pCon, SicsInterp * pSics, void *pData,
int argc, char *argv[]); int argc, char *argv[]);

32
remob.c
View File

@ -313,7 +313,8 @@ static int RemTransact(RemServer * remserver, int nChan,
int try; int try;
int argMask; int argMask;
RemChannel *rc = &remserver->rc[nChan]; RemChannel *rc = &remserver->rc[nChan];
pDynString errorResult;
try = 3; try = 3;
if (rc->timeout) { /* eat old responses */ if (rc->timeout) { /* eat old responses */
while (RemRead(rc, 0) > 0) { while (RemRead(rc, 0) > 0) {
@ -339,6 +340,20 @@ tryagain:
if (iRet <= 0) if (iRet <= 0)
goto close; goto close;
while (!StartsWith(rc->line, "TRANSACTIONFINISHED")) { while (!StartsWith(rc->line, "TRANSACTIONFINISHED")) {
if (StartsWith(rc->line, "ERROR:")) {
errorResult = CreateDynString(60, 64);
do {
RemHandle(remserver);
DynStringConcat(errorResult, rc->line);
DynStringConcat(errorResult, "\n");
iRet = RemRead(rc, 2000);
} while (!StartsWith(rc->line, "TRANSACTIONFINISHED"));
if (pCon != NULL) {
SCPrintf(pCon, eError, "ERROR: in %s:\n%s", remserver->name, GetCharArray(errorResult));
}
DeleteDynString(errorResult);
return -2;
}
RemHandle(remserver); RemHandle(remserver);
va_start(ap, cmd); va_start(ap, cmd);
arg = va_arg(ap, char *); arg = va_arg(ap, char *);
@ -448,15 +463,17 @@ static float RemobGetValue(void *pData, SConnection * pCon)
SCDeleteConnection(remserver->conn); SCDeleteConnection(remserver->conn);
} }
remserver->conn = SCCopyConnection(pCon); remserver->conn = SCCopyConnection(pCon);
none = -1.25e6; none = -1.234e32;
value = none; value = none;
snprintf(buf, sizeof(buf), "<%s", remob->name); snprintf(buf, sizeof(buf), "<%s", remob->name);
/* get value needs only spy priviledge */ /* get value needs only spy priviledge */
iRet = iRet =
RemTransact(remserver, 0, pCon, remob->name, buf, &value, ">", NULL); RemTransact(remserver, 0, pCon, remob->name, buf, &value, ">", NULL);
/*
if (iRet <= 0) { if (iRet <= 0) {
return 0.0; return 0.0;
} }
*/
if (value != none) { if (value != none) {
return value; return value;
} }
@ -654,7 +671,13 @@ int RemobAction(SConnection * pCon, SicsInterp * pSics, void *pData,
remserver->conn = SCCopyConnection(pCon); remserver->conn = SCCopyConnection(pCon);
} }
if (argc == 1) { if (argc == 1) {
iRet = RemTransact(remserver, nChan, pCon, remob->name, ">", NULL); /* filter out time stamps !=== */
iRet = RemTransact(remserver, nChan, pCon, remob->name, "!===", ">", NULL);
if (iRet < 0) {
iRet = 0;
} else {
iRet = 1;
}
} else if (strcasecmp(argv[1], "interest") == 0) { } else if (strcasecmp(argv[1], "interest") == 0) {
/* ignore interest commands, as they would not work properly */ /* ignore interest commands, as they would not work properly */
iRet = 1; iRet = 1;
@ -666,7 +689,8 @@ int RemobAction(SConnection * pCon, SicsInterp * pSics, void *pData,
cmd = Arg2Tcl0(argc - 1, argv + 1, buf, sizeof buf, remob->name); cmd = Arg2Tcl0(argc - 1, argv + 1, buf, sizeof buf, remob->name);
if (cmd) { if (cmd) {
RemTransact(remserver, nChan, pCon, cmd, ">", NULL); /* filter out time stamps !=== */
RemTransact(remserver, nChan, pCon, cmd, "!===", ">", NULL);
if (cmd != buf) if (cmd != buf)
free(cmd); free(cmd);
} }

View File

@ -2,7 +2,7 @@
* Remote objects in sicsobj. This means accessing remote objects in a different * Remote objects in sicsobj. This means accessing remote objects in a different
* SICS server from a master SICS server. * SICS server from a master SICS server.
* *
* Reading is implementd according to this scheme: * Reading is implemented according to this scheme:
* *
* * When a read connection is made between a local node and a remote node in slave, then a * * When a read connection is made between a local node and a remote node in slave, then a
* callback is installed on remote node in slave. * callback is installed on remote node in slave.
@ -17,7 +17,7 @@
* *
* COPRYRIGHT: see file COPYRIGHT * COPRYRIGHT: see file COPYRIGHT
* *
* Mark Koennecke, February 2015 * Mark Koennecke, February-May 2015
**/ **/
#include <unistd.h> #include <unistd.h>
#include <time.h> #include <time.h>
@ -31,22 +31,29 @@
#include <lld_blob.h> #include <lld_blob.h>
#include <dynstring.h> #include <dynstring.h>
#include <stptok.h> #include <stptok.h>
#include <json/json.h>
#define OOM -5001 /* out of memory */ #define OOM -5001 /* out of memory */
#define TO -5002 /* timeout */ #define TO -5002 /* timeout */
#define READACT 7654
#define POCHACT 8437
static char *login = {"RemoteMaster 3ed4c656a15f0aa45e02fd5ec429225bb93b762e7eb06cc81a0b4f6c35c76184\r\n"}; static char *login = {"RemoteMaster 3ed4c656a15f0aa45e02fd5ec429225bb93b762e7eb06cc81a0b4f6c35c76184\r\n"};
extern char *trim(char *txt); extern char *trim(char *txt);
static int transactionID = 100000;
/*---------------------- our very private data structure -------------------*/ /*---------------------- our very private data structure -------------------*/
typedef struct { typedef struct {
char *host; char *host;
int port; int port;
int readHandle; int handle;
int writeHandle; int transactHandle;
int writeInUse;
int readList; int readList;
int writeList;
unsigned int connected; unsigned int connected;
time_t nextHeartbeat; time_t nextHeartbeat;
struct json_tokener *jtok;
} RemoteOBJ, *pRemoteOBJ; } RemoteOBJ, *pRemoteOBJ;
/*----------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------*/
typedef struct { typedef struct {
@ -59,6 +66,12 @@ typedef struct {
char *remotePath; char *remotePath;
} UpdateCallback, *pUpdateCallback; } UpdateCallback, *pUpdateCallback;
/*----------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------*/
typedef struct {
int transID;
SConnection *pCon;
int waitTask;
}writeData, *pWriteData;
/*----------------------------------------------------------------------------*/
void KillRemoteOBJ(void *data) void KillRemoteOBJ(void *data)
{ {
char roTaskName[132]; char roTaskName[132];
@ -68,66 +81,13 @@ void KillRemoteOBJ(void *data)
snprintf(roTaskName,sizeof(roTaskName),"ro-%s-%d", self->host, self->port); snprintf(roTaskName,sizeof(roTaskName),"ro-%s-%d", self->host, self->port);
StopTask(pServ->pTasker,roTaskName); StopTask(pServ->pTasker,roTaskName);
free(self->host); free(self->host);
ANETclose(self->readHandle); ANETclose(self->handle);
ANETclose(self->writeHandle); ANETclose(self->transactHandle);
LLDdeleteBlob(self->readList); LLDdeleteBlob(self->readList);
LLDdeleteBlob(self->writeList);
json_tokener_free(self->jtok);
} }
} }
/*========================= reading related code ================================*/
static int RemoteReadCallback(int handle, void *userData)
{
int length;
char *pPtr, *pStart, *pEnd;
pPtr = ANETreadPtr(handle,&length);
/*
* deal with command results
*/
pStart = strstr(pPtr, "TRANSACTIONSTART");
pEnd = strstr(pPtr,"TRANSACTIONEND");
if(pStart != NULL && pEnd != NULL){
pStart = pStart + strlen("TRANSACTIONSTART");
*pEnd = '\0';
traceIO("RO","Received command - reply: %s", pStart);
pEnd += strlen("TRANSACTIONEND");
ANETreadConsume(handle,pEnd - pPtr);
}
/*
* deal with update messages
*/
pStart = strstr(pPtr, "SROC:");
pEnd = strstr(pPtr,":EROC\r\n");
if(pStart != NULL && pEnd != NULL){
pStart += strlen("SROC:");
*pEnd = '\0';
InterpExecute(pServ->pSics, pServ->dummyCon,pStart);
traceIO("RO", "Received %s from remote", pStart);
pEnd += strlen("EROC\r\n");
ANETreadConsume(handle,pEnd - pPtr);
}
/*
* deal with heartbeats
*/
if((pStart = strstr(pPtr,"Poch")) != NULL){
ANETreadConsume(handle,(pStart+4) - pPtr);
}
/*
If there is more stuff to process: recurse
*/
pPtr = ANETreadPtr(handle,&length);
if(length > 0 &&
( strstr(pPtr,":EROC\r\n") != NULL ||
strstr(pPtr,"TRANSACTIONEND") != NULL
|| strstr(pPtr,"Poch") != NULL ) ) {
RemoteReadCallback(handle,userData);
}
return 1;
}
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
static int transactCommand(int handle, char *command, char *reply, int replyLen) static int transactCommand(int handle, char *command, char *reply, int replyLen)
{ {
@ -135,7 +95,7 @@ static int transactCommand(int handle, char *command, char *reply, int replyLen)
char *prefix = {"transact "}; char *prefix = {"transact "};
int status, length, type; int status, length, type;
time_t start; time_t start;
char *pPtr; char *pPtr, *pEnd;
/* /*
* read possible dirt of the line * read possible dirt of the line
@ -144,12 +104,15 @@ static int transactCommand(int handle, char *command, char *reply, int replyLen)
ANETreadConsume(handle,length); ANETreadConsume(handle,length);
toSend = malloc(strlen(command) + strlen(prefix) + 1); toSend = malloc(strlen(command) + strlen(prefix) + 10);
if(toSend == NULL){ if(toSend == NULL){
return OOM; return OOM;
} }
strcpy(toSend, prefix); strcpy(toSend, prefix);
strcat(toSend, command); strcat(toSend, command);
if(strstr(command,"\n") == NULL){
strcat(toSend,"\r\n");
}
status = ANETwrite(handle,toSend,strlen(toSend)); status = ANETwrite(handle,toSend,strlen(toSend));
free(toSend); free(toSend);
if(status != 1){ if(status != 1){
@ -163,7 +126,8 @@ static int transactCommand(int handle, char *command, char *reply, int replyLen)
while(time(NULL) < start + 2.0){ while(time(NULL) < start + 2.0){
ANETprocess(); ANETprocess();
pPtr = ANETreadPtr(handle,&length); pPtr = ANETreadPtr(handle,&length);
if(length > 0 && strstr(pPtr,"TRANSACTIONFINISHED") != NULL){ if(length > 0 && (pEnd = strstr(pPtr,"TRANSACTIONFINISHED")) != NULL){
*pEnd = '\0';
strncpy(reply,pPtr,replyLen); strncpy(reply,pPtr,replyLen);
ANETreadConsume(handle,length); ANETreadConsume(handle,length);
return 1; return 1;
@ -191,9 +155,9 @@ static void ConnectRemoteObject(pRemoteOBJ self)
return; return;
} }
self->readHandle = ANETconnect(self->host, self->port); self->handle = ANETconnect(self->host, self->port);
self->writeHandle = ANETconnect(self->host, self->port); self->transactHandle = ANETconnect(self->host, self->port);
if(self->readHandle < 0 || self->writeHandle < 0){ if(self->handle < 0 || self->transactHandle < 0){
self->connected = 0; self->connected = 0;
traceIO("RO","Failed to connect to remote objects at %s, port %d", traceIO("RO","Failed to connect to remote objects at %s, port %d",
self->host, self->port); self->host, self->port);
@ -206,23 +170,20 @@ static void ConnectRemoteObject(pRemoteOBJ self)
Default login with hard coded manager login. Defined in Default login with hard coded manager login. Defined in
nserver.c nserver.c
*/ */
ANETwrite(self->readHandle,login,strlen(login)); ANETwrite(self->handle,login,strlen(login));
ANETwrite(self->writeHandle,login,strlen(login)); ANETwrite(self->transactHandle,login,strlen(login));
usleep(500); usleep(500);
ANETprocess(); ANETprocess();
/* /*
eat the login responses eat the login responses
*/ */
pPtr = ANETreadPtr(self->readHandle, &length); pPtr = ANETreadPtr(self->handle, &length);
ANETreadConsume(self->readHandle,length); ANETreadConsume(self->handle,length);
pPtr = ANETreadPtr(self->writeHandle, &length); pPtr = ANETreadPtr(self->transactHandle, &length);
ANETreadConsume(self->writeHandle,length); ANETreadConsume(self->transactHandle,length);
transactCommand(self->handle,"protocol set json\r\n", command,sizeof(command)-1);
/*
* install the read callback
*/
ANETsetReadCallback(self->readHandle,RemoteReadCallback, NULL, NULL);
/* /*
* Remove geterror on read nodes and reinstall callbacks for reconnects * Remove geterror on read nodes and reinstall callbacks for reconnects
@ -233,17 +194,15 @@ static void ConnectRemoteObject(pRemoteOBJ self)
node = FindHdbNode(NULL,rd.localNode,NULL); node = FindHdbNode(NULL,rd.localNode,NULL);
if(node != NULL){ if(node != NULL){
SetHdbProperty(node,"geterror",NULL); SetHdbProperty(node,"geterror",NULL);
snprintf(command,sizeof(command),"fulltransact addremotecb %s %s \r\n", snprintf(command,sizeof(command),"contextdo %d addremotecb %s %s \r\n",
rd.remoteNode, rd.localNode); READACT, rd.remoteNode, rd.localNode);
ANETwrite(self->readHandle,command,strlen(command)); ANETwrite(self->handle,command,strlen(command));
} }
status = LLDnodePtr2Next(self->readList); status = LLDnodePtr2Next(self->readList);
} }
transactCommand(self->writeHandle,"protocol set withcode\r\n", command,sizeof(command));
self->connected = 1; self->connected = 1;
self->writeInUse = 0;
} }
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
static void MarkDisconnected(pRemoteOBJ self) static void MarkDisconnected(pRemoteOBJ self)
@ -270,8 +229,8 @@ static hdbCallbackReturn ROUpdateCallback(pHdb currentNode, void *userData,
pUpdateCallback uppi = (pUpdateCallback)userData; pUpdateCallback uppi = (pUpdateCallback)userData;
hdbDataMessage *mm = NULL; hdbDataMessage *mm = NULL;
pDynString text; pDynString text;
char *prefix = {"SROC:hupdate "}; char *prefix = {"hupdate "};
char *postfix= {":EROC\r\n"}; char *postfix= {" \r\n"};
char *txt = NULL; char *txt = NULL;
int length; int length;
pHdbPropertyChange propChange = NULL; pHdbPropertyChange propChange = NULL;
@ -309,7 +268,7 @@ static hdbCallbackReturn ROUpdateCallback(pHdb currentNode, void *userData,
if(!SCisConnected(uppi->sendCon)){ if(!SCisConnected(uppi->sendCon)){
return hdbKill; return hdbKill;
} }
length = strlen("SROC:hdelprop ") + strlen(uppi->remotePath) + length = strlen("hdelprop ") + strlen(uppi->remotePath) +
strlen(propChange->key) + 10; strlen(propChange->key) + 10;
if(propChange->value != NULL){ if(propChange->value != NULL){
length += strlen(propChange->value); length += strlen(propChange->value);
@ -319,10 +278,10 @@ static hdbCallbackReturn ROUpdateCallback(pHdb currentNode, void *userData,
return hdbContinue; return hdbContinue;
} }
if(propChange->value == NULL){ if(propChange->value == NULL){
snprintf(txt,length,"SROC:hdelprop %s %s %s", uppi->remotePath, snprintf(txt,length,"hdelprop %s %s %s", uppi->remotePath,
propChange->key,postfix); propChange->key,postfix);
} else { } else {
snprintf(txt,length,"SROC:hsetprop %s %s %s %s", uppi->remotePath, snprintf(txt,length,"hsetprop %s %s %s %s", uppi->remotePath,
propChange->key,propChange->value, postfix); propChange->key,propChange->value, postfix);
} }
SCWrite(uppi->sendCon,txt,eValue); SCWrite(uppi->sendCon,txt,eValue);
@ -397,7 +356,7 @@ static int ConnectRead(pRemoteOBJ self, SConnection * pCon, ReadData rd)
* Get information about the remote node and check compatability * Get information about the remote node and check compatability
*/ */
snprintf(command,sizeof(command),"hinfo %s\r\n", rd.remoteNode); snprintf(command,sizeof(command),"hinfo %s\r\n", rd.remoteNode);
status = transactCommand(self->writeHandle,command,reply,sizeof(reply)); status = transactCommand(self->transactHandle,command,reply,sizeof(reply));
if(status != 1){ if(status != 1){
/* /*
* try a reconnect, * try a reconnect,
@ -407,7 +366,7 @@ static int ConnectRead(pRemoteOBJ self, SConnection * pCon, ReadData rd)
*/ */
self->connected = 0; self->connected = 0;
ConnectRemoteObject(self); ConnectRemoteObject(self);
status = transactCommand(self->writeHandle,command,reply,sizeof(reply)); status = transactCommand(self->transactHandle,command,reply,sizeof(reply));
if(status != 1){ if(status != 1){
SCPrintf(pCon,eWarning,"WARNING: cannot yet reach slave %s, but continuing...", SCPrintf(pCon,eWarning,"WARNING: cannot yet reach slave %s, but continuing...",
self->host); self->host);
@ -448,9 +407,9 @@ static int ConnectRead(pRemoteOBJ self, SConnection * pCon, ReadData rd)
* Install a callback on the remote node to update the master. The remote should * Install a callback on the remote node to update the master. The remote should
* then immediatly send an update which will be processed by the read callback. * then immediatly send an update which will be processed by the read callback.
*/ */
snprintf(command,sizeof(command),"fulltransact addremotecb %s %s \r\n", snprintf(command,sizeof(command),"contextdo %d addremotecb %s %s \r\n",
rd.remoteNode, rd.localNode); READACT, rd.remoteNode, rd.localNode);
ANETwrite(self->readHandle,command,strlen(command)); ANETwrite(self->handle,command,strlen(command));
return 1; return 1;
} }
@ -492,10 +451,10 @@ static int HeartbeatTask(void *pData)
{ {
pRemoteOBJ self = (pRemoteOBJ)pData; pRemoteOBJ self = (pRemoteOBJ)pData;
int status; int status;
char command[] = {"Poch\r\n"}; char command[] = {"contextdo 8437 Poch\r\n"};
if (time(NULL) > self->nextHeartbeat){ if (time(NULL) > self->nextHeartbeat){
status = ANETwrite(self->readHandle,command, strlen(command)); status = ANETwrite(self->handle,command, strlen(command));
if(status != 1){ if(status != 1){
traceIO("RO","Trying a reconnect to %s, %d", self->host, self->port); traceIO("RO","Trying a reconnect to %s, %d", self->host, self->port);
self->connected = 0; self->connected = 0;
@ -509,11 +468,13 @@ static int HeartbeatTask(void *pData)
return 1; return 1;
} }
/*============================= writing related code =========================== /*============================= writing related code ===========================
The logic here is to use the standard writeHandle when available. I expect most This works by sending the command via contextdo with a ID > 10^6. This causes
communication to be short and to happen through the writeHandle. If that one is the remote SICS to send the termination messages. The transaction IDs together
in use, a new connection will be built. with the connection responsible for it are kept in a list.
---------------------------------------------------------------------------------
suppress all superfluous OK from the slave This list is used by the write task to forward messages properly and for handling
termination.
-----------------------------------------------------------------------------------*/ -----------------------------------------------------------------------------------*/
#include <outcode.c> #include <outcode.c>
static OutCode findOutCode(char *txt) static OutCode findOutCode(char *txt)
@ -527,93 +488,153 @@ static OutCode findOutCode(char *txt)
} }
return eValue; return eValue;
} }
/*--------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
static void printSICS(char *answer, SConnection *pCon) static void CheckWriteList(int writeList,int transID, OutCode eOut, char *pText)
{ {
char line[1024], *pPtr, *pCode; int status;
OutCode eCode; writeData WD;
pPtr = answer; status = LLDnodePtr2First(writeList);
while(pPtr != NULL){ while(status == 1){
memset(line,0,sizeof(line)); LLDblobData(writeList,&WD);
pPtr = stptok(pPtr,line,sizeof(line),"\n"); if(WD.transID == transID){
if(strstr(line,"OK") == NULL){ if(strstr(pText,"COMSTART") != NULL){
pCode = strstr(line,"@@"); /* skip */
if(pCode != NULL){ } else if(strstr(pText,"COMEND") != NULL && WD.waitTask == 0) {
*pCode = '\0'; SCDeleteConnection(WD.pCon);
pCode += 2; LLDblobDelete(writeList);
eCode = findOutCode(trim(pCode)); return;
} else if(strstr(pText,"COMEND") != NULL && WD.waitTask == 1) {
/* skip */
return;
} else if(strstr(pText,"TASKSTART") != NULL){
WD.waitTask = 1 ;
LLDblobDelete(writeList);
LLDblobAppend(writeList,&WD, sizeof(writeData));
return;
} else if(strstr(pText,"TASKEND") != NULL && WD.waitTask == 1){
SCDeleteConnection(WD.pCon);
LLDblobDelete(writeList);
return;
} else { } else {
eCode = eValue; if(strstr(pText,"OK") == NULL){
SCWrite(WD.pCon,pText,eOut);
}
return;
} }
SCWrite(pCon,line,eCode);
} }
status = LLDnodePtr2Next(writeList);
} }
} }
/*---------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
static int PrepareWriteHandle(pRemoteOBJ self, SConnection *pCon, int *newHandle) static int WriteResponseTask(void *pData)
{ {
int handle, length; pRemoteOBJ self = (pRemoteOBJ)pData;
char *answer = NULL; int status, length = 0, transID;
char command[80]; char *pText, *outTxt;
json_object *message = NULL, *data = NULL;
enum json_tokener_error tokerr;
OutCode eOut;
writeData WD;
if(self->writeInUse) { if(!ANETvalidHandle(self->handle)) {
handle = ANETconnect(self->host,self->port); return 1;
if(handle < 0){
traceIO("RO","Failed to connect to %s at %d", self->host, self->port);
if(pCon != NULL){
SCPrintf(pCon,eError,"ERROR: Failed to connect to %s %d", self->host, self->port);
}
return handle;
}
ANETwrite(handle,login,strlen(login));
usleep(500);
ANETprocess();
/*
eat the login responses
*/
answer = ANETreadPtr(handle, &length);
ANETreadConsume(handle,length);
*newHandle = 1;
transactCommand(handle,"protocol set withcode\r\n", command,sizeof(command));
} else {
self->writeInUse = 1;
handle = self->writeHandle;
/*
eat dirt from the line
*/
answer = ANETreadPtr(handle, &length);
ANETreadConsume(handle,length);
} }
return handle;
pText = ANETreadPtr(self->handle,&length);
while(length > 0){
json_tokener_reset(self->jtok);
message = json_tokener_parse_ex(self->jtok,pText,length);
tokerr = self->jtok->err;
if(tokerr == json_tokener_continue){
return 1;
} else if(tokerr != json_tokener_success) {
traceIO("RO","JSON parsing error %s on %s from %s %d",
json_tokener_errors[tokerr], pText, self->host, self->jtok->char_offset);
ANETreadConsume(self->handle,length);
return 1;
}
if(json_object_get_type(message) != json_type_object) {
traceIO("RO","Received JSON of bad type in %s from %s",pText,self->host);
ANETreadConsume(self->handle,length);
return 1;
}
/*
we need to consume here what has been parsed.
The char_offset in the tokenizer structure might tell us that...
*/
ANETreadConsume(self->handle,self->jtok->char_offset);
/*
Received a valid message, process
*/
data = json_object_object_get(message,"trans");
if(data == NULL){
traceIO("RO","No transaction ID found in %s from %s", pText,self->host);
return 1;
}
transID = json_object_get_int(data);
data = json_object_object_get(message,"flag");
if(data == NULL){
traceIO("RO","No flag found in %s from %s", pText,self->host);
return 1;
}
outTxt = (char *)json_object_get_string(data);
eOut = findOutCode(outTxt);
data = json_object_object_get(message,"data");
if(data == NULL){
traceIO("RO","No data found in %s from %s", pText,self->host);
return 1;
}
pText = (char *)json_object_get_string(data);
traceIO("RO","Received:%s:%d:%d:%s",self->host,transID,eOut,pText);
/*
do nothing on Poch
*/
if(transID == POCHACT){
pText = ANETreadPtr(self->handle,&length);
json_object_put(message);
continue;
}
/*
process update messages
*/
if(transID == READACT){
if(strstr(pText,"hupdate") != NULL || strstr(pText,"prop") != NULL){
InterpExecute(pServ->pSics,pServ->dummyCon,pText);
}
traceIO("RO","Received %s from remote",pText);
pText = ANETreadPtr(self->handle,&length);
json_object_put(message);
continue;
}
/*
check write List
*/
CheckWriteList(self->writeList,transID,eOut,pText);
json_object_put(message);
pText = ANETreadPtr(self->handle,&length);
}
return 1;
} }
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
static void ProcessWriteResponse(pRemoteOBJ self, int handle, SConnection *pCon) static int IncrementTransactionID()
{ {
char *answer = NULL, *pEnd, *command = NULL; transactionID++;
int length; if(transactionID >= 200000){
transactionID = 100000;
while(1){
TaskYield(pServ->pTasker);
if(!ANETvalidHandle(handle)){
SCPrintf(pCon,eError,"ERROR: Disconnected from %s", self->host);
break;
}
answer = ANETreadPtr(handle,&length);
if(length > 0 && (pEnd = strstr(answer,"TRANSACTIONFINISHED")) != NULL){
if(pCon != NULL){
*pEnd = '\0';
printSICS(answer,pCon);
}
traceIO("RO","%s:%d: Received %s", self->host, self->port,answer);
ANETreadConsume(handle,length);
break;
}
} }
return transactionID;
} }
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
static hdbCallbackReturn ROWriteCallback(pHdb currentNode, void *userData, static hdbCallbackReturn ROWriteCallback(pHdb currentNode, void *userData,
@ -626,14 +647,10 @@ static hdbCallbackReturn ROWriteCallback(pHdb currentNode, void *userData,
pDynString data; pDynString data;
char *remoteNode; char *remoteNode;
char *command, *answer, *pEnd; char *command, *answer, *pEnd;
writeData WD;
if((mm = GetHdbSetMessage(mes)) != NULL){ if((mm = GetHdbSetMessage(mes)) != NULL){
pCon = (SConnection *)mm->callData; pCon = (SConnection *)mm->callData;
handle = PrepareWriteHandle(self,pCon,&newHandle);
if(handle < 0){
return hdbAbort;
}
/* /*
build the command to send build the command to send
@ -648,53 +665,32 @@ static hdbCallbackReturn ROWriteCallback(pHdb currentNode, void *userData,
} }
return hdbAbort; return hdbAbort;
} }
snprintf(command,length,"transact hset %s %s\r\n",remoteNode, GetCharArray(data)); WD.pCon = SCCopyConnection(pCon);
WD.waitTask = 0;
WD.transID = IncrementTransactionID();
snprintf(command,length,"contextdo %d hset %s %s\r\n",
WD.transID, remoteNode, GetCharArray(data));
/* /*
write write
*/ */
traceIO("RO","%s:%d: Sending %s ", self->host, self->port, command); traceIO("RO","%s:%d: Sending %s ", self->host, self->port, command);
status = ANETwrite(handle,command,strlen(command)); LLDblobAppend(self->writeList,&WD,sizeof(writeData));
status = ANETwrite(self->handle,command,strlen(command));
free(command); free(command);
DeleteDynString(data); DeleteDynString(data);
if(status < 0){ if(status < 0){
if(pCon != NULL){ self->connected = 0;
SCPrintf(pCon,eError,"ERROR: remote %s on %s disconnected", remoteNode, self->host); ConnectRemoteObject(self);
} if(self->connected == 0){
return hdbAbort; if(pCon != NULL){
} SCPrintf(pCon,eError,"ERROR: remote %s on %s disconnected",
remoteNode, self->host);
/* }
wait for a response: TRANSACTIONFINISHED return hdbAbort;
*/
ProcessWriteResponse(self,handle,pCon);
/*
Is there a termination script?
*/
command = GetHdbProp(currentNode,"termscript");
if(command != NULL){
while(1) {
TaskYield(pServ->pTasker);
Tcl_Eval(InterpGetTcl(pServ->pSics),command);
answer = (char *)Tcl_GetStringResult(InterpGetTcl(pServ->pSics));
if(strstr(answer,"idle") != NULL){
answer = ANETreadPtr(handle,&length);
printSICS(answer,pCon);
traceIO("RO","%s:%d:Received %s", self->host,self->port,answer);
ANETreadConsume(handle,length);
break;
}
} }
} }
return hdbContinue;
if(newHandle){
ANETclose(handle);
} else {
self->writeInUse = 0;
}
} }
return hdbContinue; return hdbContinue;
@ -722,12 +718,17 @@ static int ConnectWrite(pRemoteOBJ self, SConnection *pCon, ReadData rd)
SetHdbProperty(localNode,"remotewrite",rd.remoteNode); SetHdbProperty(localNode,"remotewrite",rd.remoteNode);
AppendHipadabaCallback(localNode, MakeHipadabaCallback(ROWriteCallback, AppendHipadabaCallback(localNode, MakeHipadabaCallback(ROWriteCallback,
self,NULL)); self,NULL));
/*
TODO: The connected write nodes should be held in a list in order to be able to
remove the write callbacks when deleting the remote object. As removing remote
objects usually only happens when SICS shuts down this is not so important.
*/
/* /*
* Get information about the remote node and check compatability * Get information about the remote node and check compatability
*/ */
snprintf(command,sizeof(command),"hinfo %s\r\n", rd.remoteNode); snprintf(command,sizeof(command),"hinfo %s\r\n", rd.remoteNode);
status = transactCommand(self->writeHandle,command,reply,sizeof(reply)); status = transactCommand(self->transactHandle,command,reply,sizeof(reply));
if(status != 1){ if(status != 1){
SCPrintf(pCon,eWarning,"WARNING: cannot yet reach slave %s, but continuing...", SCPrintf(pCon,eWarning,"WARNING: cannot yet reach slave %s, but continuing...",
self->host); self->host);
@ -784,61 +785,21 @@ static int ConnectwriteCmd(pSICSOBJ ccmd, SConnection * pCon,
/*============================ remote execute =================================*/ /*============================ remote execute =================================*/
static int RemoteExecute(pRemoteOBJ self, SConnection *pCon, char *command) static int RemoteExecute(pRemoteOBJ self, SConnection *pCon, char *command)
{ {
int status, handle, newHandle = 0, length; int status;
char *answer, *pEnd; char answer[65536];
handle = PrepareWriteHandle(self,pCon,&newHandle);
if(handle < 0){
return 0;
}
/* /*
write, thereby taking care to prefix with transact and for proper termination write, thereby taking care to prefix with transact and for proper termination
*/ */
if(strstr(command,"transact") == NULL){ memset(answer,0,sizeof(answer)-1);
ANETwrite(handle,"transact ", sizeof("transact ")); status = transactCommand(self->transactHandle,command,answer,sizeof(answer));
} if(status == 1){
status = ANETwrite(handle,command,strlen(command)); SCWrite(pCon,answer,eValue);
if(strstr(command,"\n") == NULL){
ANETwrite(handle,"\r\n",2);
}
if(status < 0){
traceIO("RO","Disconnect from %s while executing %s", self->host, command);
if(pCon != NULL){
SCPrintf(pCon,eError,"ERROR: Disconnected from %s %d", self->host, self->port);
}
return 0;
}
/*
wait for response
*/
while(1){
TaskYield(pServ->pTasker);
if(!ANETvalidHandle(handle)){
if(pCon != NULL){
SCPrintf(pCon,eError,"ERROR: Disconnected from %s %d", self->host, self->port);
}
break;
}
answer = ANETreadPtr(handle,&length);
if(length > 0 && (pEnd = strstr(answer,"TRANSACTIONFINISHED")) != NULL){
if(pCon != NULL){
*pEnd = '\0';
SCPrintf(pCon,eValue,answer);
}
ANETreadConsume(handle,length);
break;
}
}
if(newHandle){
ANETclose(handle);
} else { } else {
self->writeInUse = 0; SCPrintf(pCon,eError,"ERROR: Disconnected from %s %d", self->host, self->port);
} }
return 1; return status;
} }
/*------------------------------------------------------------------------------*/ /*------------------------------------------------------------------------------*/
static int RemoteExecuteCmd(pSICSOBJ ccmd, SConnection * pCon, static int RemoteExecuteCmd(pSICSOBJ ccmd, SConnection * pCon,
@ -920,6 +881,8 @@ static int MakeRemoteObject(SConnection *pCon, SicsInterp *pSics, void *pData,
self->host = strdup(argv[2]); self->host = strdup(argv[2]);
self->port = atoi(argv[3]); self->port = atoi(argv[3]);
self->readList = LLDblobCreate(); self->readList = LLDblobCreate();
self->writeList = LLDblobCreate();
self->jtok = json_tokener_new();
ConnectRemoteObject(self); ConnectRemoteObject(self);
cmd = AddSICSHdbPar(pNew->objectNode, cmd = AddSICSHdbPar(pNew->objectNode,
@ -949,6 +912,8 @@ static int MakeRemoteObject(SConnection *pCon, SicsInterp *pSics, void *pData,
snprintf(roTaskName,sizeof(roTaskName),"ro-%s-%d", self->host, self->port); snprintf(roTaskName,sizeof(roTaskName),"ro-%s-%d", self->host, self->port);
TaskRegisterN(pServ->pTasker, roTaskName, HeartbeatTask, NULL,NULL,self,1); TaskRegisterN(pServ->pTasker, roTaskName, HeartbeatTask, NULL,NULL,self,1);
snprintf(roTaskName,sizeof(roTaskName),"rocom-%s-%d", self->host, self->port);
TaskRegisterN(pServ->pTasker, roTaskName, WriteResponseTask, NULL,NULL,self,1);
return status; return status;
} }

View File

@ -201,7 +201,7 @@ static int StatCmd(pSICSOBJ self, SConnection *pCon, pHdb commandNode,
} }
average = (double)sum/(double)length; average = (double)sum/(double)length;
SCPrintf(pCon,eValue,"Stat:sum,max,min,av = %d,%d,%d,%f", sum,max,min,average); SCPrintf(pCon,eValue,"Stat:sum,max,min,av = %ld,%ld,%ld,%f", sum,max,min,average);
return 1; return 1;
} }

4
scan.c
View File

@ -152,6 +152,8 @@ pScanData CreateScanObject(char *pRecover, char *pHeader, pCounter pCount,
/* assign various things */ /* assign various things */
if (pRecover) { if (pRecover) {
strlcpy(pNew->pRecover, pRecover,1024); strlcpy(pNew->pRecover, pRecover,1024);
} else {
memset(pNew->pRecover,0,sizeof(pNew->pRecover));
} }
if (pHeader) { if (pHeader) {
strlcpy(pNew->pHeaderFile, pHeader,1024); strlcpy(pNew->pHeaderFile, pHeader,1024);
@ -597,7 +599,7 @@ static int ScanLoop(pScanData self)
InvokeCallBack(self->pCall, SCANPOINT, self); InvokeCallBack(self->pCall, SCANPOINT, self);
self->WriteScanPoints(self, i); self->WriteScanPoints(self, i);
if (self->pRecover) { if (strlen(self->pRecover) > 10) {
WriteRecover(self); WriteRecover(self);
} }
} }

View File

@ -404,6 +404,7 @@ static char *SctActionHandler(void *actionData, char *lastReply,
char *errorScript = NULL; char *errorScript = NULL;
char *send = NULL; char *send = NULL;
int i; int i;
int j;
SConnection *con; SConnection *con;
char eprop[80]; char eprop[80];
char msg[1024]; char msg[1024];
@ -431,23 +432,24 @@ static char *SctActionHandler(void *actionData, char *lastReply,
* property result to the data from the device. Read this now and * property result to the data from the device. Read this now and
* print it if diagnostics is required. * print it if diagnostics is required.
*/ */
SetProp(node, controller->node, "result", lastReply);
script = NULL; script = NULL;
if (!commError && controller->verbose && lastReply != NULL if (lastReply != NULL) {
&& *lastReply != '\0') { SetProp(node, controller->node, "result", lastReply);
SCPrintf(con, eLog, "%6.3f reply : %s\n", secondsOfMinute(), lastReply); if (*lastReply != '\0') {
if (!commError && controller->verbose) {
SCPrintf(con, eLog, "%6.3f reply : %s\n", secondsOfMinute(), lastReply);
}
if(!commError && controller->fd != NULL) {
fprintf(controller->fd, "%6.3f reply : %s\n", secondsOfMinute(), lastReply);
}
if(data != NULL && data->controller != NULL) {
traceIO(data->controller->node->name, "reply:%s", lastReply);
} else {
traceIO("sctunknown", "reply:%s", lastReply);
}
}
} }
if(!commError && controller->fd != NULL && lastReply != NULL && *lastReply != '\0'){
fprintf(controller->fd, "%6.3f reply : %s\n", secondsOfMinute(), lastReply);
}
if(lastReply != NULL && *lastReply != '\0'){
if(data != NULL && data->controller != NULL){
traceIO(data->controller->node->name, "reply:%s", lastReply);
} else {
traceIO("sctunknown", "reply:%s", lastReply);
}
}
/* /*
* Make sure that the state property is set to the name of the property * Make sure that the state property is set to the name of the property
* which holds the name of the script to run at this stage. * which holds the name of the script to run at this stage.
@ -521,7 +523,7 @@ static char *SctActionHandler(void *actionData, char *lastReply,
traceIO(data->controller->node->name, "ERROR: action {%s} in {%s} node %s:\nERROR: %s", traceIO(data->controller->node->name, "ERROR: action {%s} in {%s} node %s:\nERROR: %s",
data->name, origScript, path, result); data->name, origScript, path, result);
} else { } else {
traceIO("sctunknown", "reply:%s", "ERROR: action {%s} in {%s} node %s:\nERROR: %s", traceIO("sctunknown", "ERROR: action {%s} in {%s} node %s:\nERROR: %s",
data->name, origScript, path, result); data->name, origScript, path, result);
} }
} }
@ -529,6 +531,21 @@ static char *SctActionHandler(void *actionData, char *lastReply,
if (strcasecmp(data->name, "read") == 0) { if (strcasecmp(data->name, "read") == 0) {
SetHdbProperty(node, "geterror", result); SetHdbProperty(node, "geterror", result);
} }
/* Sanitize the text to reduce TCL problems with unbalanced and substituted items */
for (j = 0; msg[j]; ++j) {
switch (msg[j]) {
case '{':
case '}':
case '[':
case ']':
case '<':
case '>':
case '\'':
case '"':
case '$':
msg[j] = '_';
}
}
SetHdbProperty(node, eprop, msg); SetHdbProperty(node, eprop, msg);
blank = strchr(origScript, ' '); blank = strchr(origScript, ' ');
if (blank != NULL) { if (blank != NULL) {
@ -544,6 +561,21 @@ static char *SctActionHandler(void *actionData, char *lastReply,
} }
cnt++; cnt++;
snprintf(msg, sizeof msg, "%dx {%s}: %s", cnt, origScript, result); snprintf(msg, sizeof msg, "%dx {%s}: %s", cnt, origScript, result);
/* Sanitize the text to reduce TCL problems with unbalanced and substituted items */
for (j = 0; msg[j]; ++j) {
switch (msg[j]) {
case '{':
case '}':
case '[':
case ']':
case '<':
case '>':
case '\'':
case '"':
case '$':
msg[j] = '_';
}
}
SetHdbProperty(node, eprop, msg); SetHdbProperty(node, eprop, msg);
send = NULL; send = NULL;
free(script); free(script);
@ -951,12 +983,15 @@ int SctAddPollNode(SctController * controller, Hdb * node, double interval,
{ {
SctData *data; SctData *data;
hdbCallback *cb; hdbCallback *cb;
char nodePath[512], info[1024];
if (!FindHdbCallbackData(node, controller)) { if (!FindHdbCallbackData(node, controller)) {
cb = MakeHipadabaCallback(SctMainCallback, controller, NULL); cb = MakeHipadabaCallback(SctMainCallback, controller, NULL);
assert(cb); assert(cb);
AppendHipadabaCallback(node, cb); AppendHipadabaCallback(node, cb);
SetHdbProperty(node, "geterror", "Not read yet"); GetHdbPath(node, nodePath, sizeof nodePath);
snprintf(info, 1023, "%s: Not read yet", nodePath);
SetHdbProperty(node, "geterror", info);
} }
data = calloc(1, sizeof(*data)); data = calloc(1, sizeof(*data));
@ -1585,8 +1620,19 @@ static int SctProcessCmd(pSICSOBJ ccmd, SConnection * con,
startTime = time(NULL); startTime = time(NULL);
DevQueue(c->devser, data, WritePRIO, DevQueue(c->devser, data, WritePRIO,
SctWriteHandler, SctTransactMatch, NULL, SctDataInfo); SctWriteHandler, SctTransactMatch, NULL, SctDataInfo);
while (data->busy == 1 && time(NULL) < startTime + 20) {
while (data->busy == 1){
TaskYield(pServ->pTasker); TaskYield(pServ->pTasker);
if(time(NULL) >= startTime + 20) {
/*
if data would still come after such a long timeout, it
might end up in the next action: see comment in devser.c
*/
SCPrintf(con,eError,"ERROR: timeout processing node %s", par[0]->value.v.text);
DevRemoveAction(c->devser,data);
SctKillData(data);
return 0;
}
} }
SctKillData(data); SctKillData(data);

View File

@ -203,7 +203,7 @@ static int StartComTaskCmd(pSICSOBJ ccmd, SConnection * con,
Hdb * cmdNode, Hdb * par[], int nPar) Hdb * cmdNode, Hdb * par[], int nPar)
{ {
char *priority, *sendData; char *priority, *sendData;
int lID; long lID;
ComTaskManager *manni = NULL; ComTaskManager *manni = NULL;
if(nPar < 2) { if(nPar < 2) {
@ -294,7 +294,7 @@ const char *GetComTaskReply(ComTaskManager *manager,
static int GetComTaskReplyCmd(pSICSOBJ ccmd, SConnection * con, static int GetComTaskReplyCmd(pSICSOBJ ccmd, SConnection * con,
Hdb * cmdNode, Hdb * par[], int nPar) Hdb * cmdNode, Hdb * par[], int nPar)
{ {
int lID; long lID;
int length; int length;
ComTaskManager *manni = NULL; ComTaskManager *manni = NULL;
const char *reply; const char *reply;
@ -311,7 +311,7 @@ static int GetComTaskReplyCmd(pSICSOBJ ccmd, SConnection * con,
SCPrintf(con,eError,"No reply for %ld found", lID); SCPrintf(con,eError,"No reply for %ld found", lID);
return 0; return 0;
} else { } else {
SCPrintf(con,eValue,"%d = %s", lID, reply); SCPrintf(con,eValue,"%ld = %s", lID, reply);
} }
return 1; return 1;

517
servlog.c
View File

@ -47,16 +47,18 @@
- NETWrites log message (if enabled) before attempt to write to file - NETWrites log message (if enabled) before attempt to write to file
- uses OpenVerifyLogFile helper function (removed duplicate code) - uses OpenVerifyLogFile helper function (removed duplicate code)
-----------------------------------------------------------------------------*/ -----------------------------------------------------------------------------*/
#include <stdarg.h>
#include "fortify.h" #include "fortify.h"
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <assert.h> #include <assert.h>
#include <string.h> #include <string.h>
#include <ctype.h> #include <ctype.h>
#include <time.h>
#include <sys/time.h>
#include <strlutil.h> #include <strlutil.h>
#include "ifile.h" #include "ifile.h"
#include "conman.h"
#include "servlog.h" #include "servlog.h"
#include "network.h" #include "network.h"
@ -69,24 +71,142 @@
this the following code is necessary. this the following code is necessary.
*/ */
typedef struct __LogLog { typedef struct __LogLog {
SConnection *pCon; pSICSLogHook pFunc;
OutCode iOut; void *pData;
int iAllFlag; unsigned int code_bits;
struct __LogLog *pNext; struct __LogLog *pNext;
struct __LogLog *pPrevious; struct __LogLog *pPrevious;
} CaptureEntry, *pCaptureEntry; } CaptureEntry, *pCaptureEntry;
static pCaptureEntry pCapture = NULL; static pCaptureEntry pCapture = NULL;
/*------------------------------------------------------------------------*/ /*------------------------------------------------------------------------*/
#include "outcode.c" /* for pCode */
int KillCapture(SConnection * pCon) const char* OutCodeToTxt(OutCode eOut)
{
switch (eOut) {
case eInternal: return "Int"; /* internal */
case eCommand: return "Cmd"; /* reserved, not used */
case eHWError: return "ErH"; /* reserved, used only for SICSLog */
case eInError: return "ErI"; /* reserved, used as a mark in the handling of output codes */
case eStatus: return "Sta"; /* reserved, deprecated */
case eValue: return "Val"; /* value reponse: copied into Tcl */
case eStart: return "Beg"; /* start message */
case eFinish: return "End"; /* finish message */
case eEvent: return "Evt"; /* some callback messages */
case eWarning: return "Wrn"; /* warnings */
case eError: return "Err"; /* error: copied into Tcl */
case eHdbValue: return "HVa"; /* hipadaba value chnage */
case eHdbEvent: return "HEv"; /* Hipadaba event */
case eLog: return "Log"; /* log message: is always written to client */
case eLogError: return "ErL"; /* error message to log: is always written to client */
}
return "???";
}
const char* OutCodeToText(OutCode eOut)
{
switch (eOut) {
case eInternal: return "Internal";
case eCommand: return "Command";
case eHWError: return "HWError";
case eInError: return "InError";
case eStatus: return "Status";
case eValue: return "Value";
case eStart: return "Start";
case eFinish: return "Finish";
case eEvent: return "Event";
case eWarning: return "Warning";
case eError: return "Error";
case eHdbValue: return "HdbValue";
case eHdbEvent: return "HdbEvent";
case eLog: return "Log";
case eLogError: return "LogError";
}
return "Unknown";
}
int OutCodeFromText(const char *text, OutCode *outcode)
{
int i;
for (i = 0; i < iNoCodes; ++i) {
if (strcasecmp(text, pCode[i]) == 0) {
if (outcode)
*outcode = i;
return i;
}
}
return -1;
}
static unsigned int find_code_bits(const char *p1, const char *p2) {
/* may be outcode, try find it */
int i;
const char *pShort;
const char *pLong;
size_t len = p2 - p1;
if (len == 3 && strncasecmp(p1, "all", 3) == 0)
return (1 << iNoCodes) - 1;
for (i = 0; i < iNoCodes; ++i) {
pShort = OutCodeToTxt(i);
if (pShort && strncasecmp(p1, pShort, len) == 0)
return 1 << i;
pLong = OutCodeToText(i);
if (pLong && strlen(pLong) == len) {
if (strncasecmp(p1, pLong, len) == 0) {
return 1 << i;
}
}
}
return 0;
}
char *AddSICSLogHook(pSICSLogHook func, const char *pCodes, void *pData)
{
unsigned int code_bits = 0;
if (strcasecmp("all", pCodes) == 0)
code_bits = (1 << iNoCodes) - 1;
else {
const char *p1, *p2;
p1 = pCodes;
while (NULL != (p2 = strchr(p1, ','))) {
/* TODO [p1:p2) */
code_bits |= find_code_bits(p1, p2);
p1 = p2 + 1;
}
/* p1 points at the last or only code */
/* TODO p1 */
code_bits |= find_code_bits(p1, p1 + strlen(p1));
}
if (code_bits != 0) {
pCaptureEntry pNew;
pNew = (pCaptureEntry) malloc(sizeof(CaptureEntry));
if (!pNew) {
SICSLogWrite("Out of memory in LogCapture", eInternal);
return NULL;
}
if (pCapture) {
pCapture->pPrevious = pNew;
}
pNew->pPrevious = NULL;
pNew->pNext = pCapture;
pCapture = pNew;
pNew->code_bits = code_bits;
pNew->pFunc = func;
pNew->pData = pData;
}
return NULL;
}
/* Remove any and all hooks with this pData */
char *RemSICSLogHook(void *pData)
{ {
pCaptureEntry pCurrent, pTemp; pCaptureEntry pCurrent, pTemp;
/* find first */ /* find first */
pCurrent = pCapture; pCurrent = pCapture;
while (pCurrent != NULL) { while (pCurrent != NULL) {
if (pCon == pCurrent->pCon) { if (pData == pCurrent->pData) {
/* relink */ /* relink */
if (pCurrent->pPrevious) { if (pCurrent->pPrevious) {
pCurrent->pPrevious->pNext = pCurrent->pNext; pCurrent->pPrevious->pNext = pCurrent->pNext;
@ -104,88 +224,27 @@ int KillCapture(SConnection * pCon)
pCurrent = pCurrent->pNext; pCurrent = pCurrent->pNext;
} }
} }
return 1; return NULL;
} }
/* Return bitmask of any and all hooks with this pData */
/* ------------------------------------------------------------------------ unsigned int GetSICSLogHook(void *pData)
the command function:
Syntax:
Kill kills all logging
Log OutCode starts loggin OutCode events
All starts logging all events
-------------------------------------------------------------------------- */
#include "outcode.c" /* for pCode */
int LogCapture(SConnection * pCon, SicsInterp * pSics, void *pData,
int argc, char *argv[])
{ {
pCaptureEntry pNew = NULL; pCaptureEntry pCurrent, pTemp;
char pBueffel[512]; unsigned int code_bits = 0;
int i;
/* check no af args */ /* find first */
if (argc < 2) { pCurrent = pCapture;
snprintf(pBueffel,sizeof(pBueffel)-1, "Insufficient number of argumenst to %s", argv[0]); while (pCurrent != NULL) {
SCWrite(pCon, pBueffel, eError); if (pData == pCurrent->pData) {
return 0; code_bits |= pCurrent->code_bits;
}
pCurrent = pCurrent->pNext;
} }
argtolower(argc, argv); return code_bits;
/* Branch according to argv[1] */
if (strcmp(argv[1], "kill") == 0) {
KillCapture(pCon);
return 1;
} else if (strcmp(argv[1], "all") == 0) {
pNew = (pCaptureEntry) malloc(sizeof(CaptureEntry));
if (!pNew) {
SICSLogWrite("Out of memory in LogCapture", eInternal);
return 0;
}
if (pCapture) {
pCapture->pPrevious = pNew;
}
pNew->pPrevious = NULL;
pNew->pNext = pCapture;
pCapture = pNew;
pNew->iAllFlag = 1;
pNew->pCon = pCon;
return 1;
} else {
/* must be outcode, try find it */
i = 0;
while (pCode[i] != NULL) {
if (strcmp(argv[1], pCode[i]) == 0) {
break;
}
i++;
}
if (i > iNoCodes) {
snprintf(pBueffel,sizeof(pBueffel)-1, "OutPutCode %s not recognized in %s", argv[1],
argv[0]);
SCWrite(pCon, pBueffel, eError);
return 0;
}
/* create a new one */
pNew = (pCaptureEntry) malloc(sizeof(CaptureEntry));
if (!pNew) {
SICSLogWrite("Out of memory in LogCapture", eInternal);
return 0;
}
if (pCapture) {
pCapture->pPrevious = pNew;
}
pNew->pPrevious = NULL;
pNew->pNext = pCapture;
pCapture = pNew;
pNew->iAllFlag = 0;
pNew->pCon = pCon;
pNew->iOut = i;
return 1;
}
return 0;
} }
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
static int HasLineFeed(char *pText) static int HasLineFeed(char *pText)
{ {
@ -203,28 +262,67 @@ static int HasLineFeed(char *pText)
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
#define MAXLOG 10000 static const char* timestamp(struct timeval *tp, char delim) {
#define MAXFILES 20 static char ts[80];
int year, month, day;
int hour, min, sec, usec;
struct timeval tv;
struct tm *time;
if (tp)
tv = *tp;
else
gettimeofday(&tv, NULL);
time = localtime(&tv.tv_sec);
year = 1900 + time->tm_year;
month = time->tm_mon + 1;
day = time->tm_mday;
hour = time->tm_hour;
min = time->tm_min;
sec = time->tm_sec;
usec = (int) tv.tv_usec;
snprintf(ts, 80, "%04d-%02d-%02dT%02d%c%02d%c%02d.%06d",
year, month, day, hour, delim, min, delim, sec, usec);
return ts;
}
/*---------------------------------------------------------------------------*/
#define MAXLOG 100000
#define MAXFILES 100
static FILE *fLogFile = NULL; static FILE *fLogFile = NULL;
static int iFile = 0; static int iFile = 0;
static int iLineCount = 0; static int iLineCount = 0;
static int iLogUsable = 1; static int iLogUsable = 1;
static char filnam[1024];
static char prevfilnam[1024];
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
int OpenVerifyLogFile() int OpenVerifyLogFile()
{ {
char pFile[256]; char pFile[256];
char filnam[512];
char *pChar = NULL; char *pChar = NULL;
char fPath[1024];
pChar = getenv("SICS_INIT_LOGPATH");
if (!pChar) {
snprintf(fPath, sizeof(fPath) - 1, "%s/", "../log");
} else {
snprintf(fPath, sizeof(fPath) - 1, "%s/", pChar);
}
pChar = IFindOption(pSICSOptions, "LogFileBaseName"); pChar = IFindOption(pSICSOptions, "LogFileBaseName");
if (!pChar) { /* Try to write to file "server" in */ if (!pChar) { /* Try to write to file "server" in */
strcpy(pFile, "server"); strcpy(pFile, "server");
} else { } else {
strlcpy(pFile, pChar, 255); strlcpy(pFile, pChar, sizeof(pFile) - 1);
} }
snprintf(filnam, 511, "%s%2.2d.log", pFile, iFile);
snprintf(filnam, sizeof(filnam) - 1, "%s%s_%19.19s.%02d.log", fPath, pFile, timestamp(NULL, '-'), iFile);
iFile++;
if (iFile >= MAXFILES) {
iFile = 0;
}
fLogFile = fopen(filnam, "w"); fLogFile = fopen(filnam, "w");
if (!fLogFile) { if (!fLogFile) {
fprintf(stderr, "ERROR: Cannot open logfile %s for writing\n", pFile); fprintf(stderr, "ERROR: Cannot open logfile %s for writing\n", pFile);
@ -242,23 +340,21 @@ void SICSLogEnable(int flag)
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
void SICSLogWrite(char *pText, OutCode eOut) static void SICSLogWriteFile(char *pText, OutCode eOut, struct timeval *tp)
{ {
char pFile[256];
char *pChar = NULL;
pCaptureEntry pCurrent; pCaptureEntry pCurrent;
char pBueffel[256]; int text_len;
#ifdef NOLOG #ifdef NOLOG
return; return;
#endif #endif
text_len = strlen(pText);
/* do all captured */ /* do all captured */
pCurrent = pCapture; pCurrent = pCapture;
while (pCurrent) { while (pCurrent) {
if ((pCurrent->iOut == eOut) || (pCurrent->iAllFlag == 1)) { if ((pCurrent->code_bits & (1 << eOut))) {
ANETwrite(pCurrent->pCon->sockHandle, pText, strlen(pText)); pCurrent->pFunc(pText, eOut, pCurrent->pData);
ANETwrite(pCurrent->pCon->sockHandle, "\n", 1);
} }
pCurrent = pCurrent->pNext; pCurrent = pCurrent->pNext;
} }
@ -273,23 +369,242 @@ void SICSLogWrite(char *pText, OutCode eOut)
return; return;
} }
iLogUsable = OpenVerifyLogFile(); iLogUsable = OpenVerifyLogFile();
iLineCount = 0;
} }
/* switch file if too many lines */ /* switch file if too many lines */
if (iLineCount >= MAXLOG) { if (iLineCount >= MAXLOG) {
fclose(fLogFile); strcpy(prevfilnam, filnam);
fLogFile = NULL; FILE *prevlog = fLogFile;
iFile++;
iLineCount = 0;
if (iFile >= MAXFILES) {
iFile = 0;
}
iLogUsable = OpenVerifyLogFile(); iLogUsable = OpenVerifyLogFile();
iLineCount = 0;
fprintf(prevlog, "%s: <<<close logfile>>> to %s\n",
timestamp(NULL, ':'),
filnam);
fclose(prevlog);
if (1 == iLogUsable) {
fprintf(fLogFile, "%s: <<<open logfile>>> from %s\n",
timestamp(NULL, ':'),
prevfilnam);
iLineCount++;
}
} }
if (1 == iLogUsable) { if (1 == iLogUsable) {
fprintf(fLogFile, "%s\n", pText); if (iLineCount == 0)
fprintf(fLogFile, "%s: <<<open logfile>>>\n", timestamp(NULL, ':'));
fprintf(fLogFile, "%s:%s:", timestamp(tp, ':'), OutCodeToTxt(eOut));
fprintf(fLogFile, "%s", pText);
if (text_len < 1 || pText[text_len - 1] != '\n')
fprintf(fLogFile, "\n");
fflush(fLogFile); fflush(fLogFile);
iLineCount++; iLineCount++;
} }
} }
void SICSLogWriteTimeCode(char *pText, OutCode eOut, struct timeval *tp, char code)
{
char buf[200];
const char *cp;
int idx = 0;
struct timeval tv;
if (tp == NULL) {
gettimeofday(&tv, NULL);
tp = &tv;
}
if (isalnum(code)) {
buf[idx++] = code;
buf[idx++] = ':';
}
cp = pText;
while (*cp) {
if (*cp == '\n') {
buf[idx++] = '\n';
buf[idx++] = '\0';
SICSLogWriteFile(buf, eOut, tp);
idx = 0;
buf[idx++] = '*';
buf[idx++] = ':';
} else if (*cp == '\r') {
buf[idx++] = '\\';
buf[idx++] = 'r';
} else if (*cp == '\t') {
buf[idx++] = '\\';
buf[idx++] = 't';
} else if (*cp < ' ' || *cp > '~') {
const char hex[] = "0123456789ABCDEF";
buf[idx++] = '<';
buf[idx++] = hex[(*cp >> 4) & 0xF];
buf[idx++] = hex[(*cp) & 0xF];
buf[idx++] = '>';
} else {
buf[idx++] = *cp;
}
cp++;
if (idx > 132) {
buf[idx++] = '\n';
buf[idx++] = '\0';
SICSLogWriteFile(buf, eOut, tp);
idx = 0;
buf[idx++] = '*';
buf[idx++] = ':';
}
}
/* Suppress the spurious blank lines caused by trailing newlines */
if (idx == 2 && buf[0] == '*' && buf[1] == ':')
return;
if (idx > 0) {
buf[idx++] = '\n';
buf[idx++] = '\0';
SICSLogWriteFile(buf, eOut, tp);
}
}
void SICSLogWriteCode(char *pText, OutCode eOut, char code)
{
SICSLogWriteTimeCode(pText, eOut, NULL, code);
}
void SICSLogWriteTime(char *pText, OutCode eOut, struct timeval *tp)
{
SICSLogWriteTimeCode(pText, eOut, tp, 'L');
}
void SICSLogWrite(char *pText, OutCode eOut)
{
SICSLogWriteTime(pText, eOut, NULL);
}
void SICSLogWriteHexTime(const char *text, int count, OutCode eOut,
struct timeval *tp)
{
const char hex[] = "0123456789ABCDEF";
char addr[20], left[80], right[80];
char *lp = left;
char *rp = right;
int i;
int duplicates;
/* Limit the output */
if (count > 1024)
count = 1024;
duplicates = 0;
for (i = 0; i < count; ++i) {
if ((i & 0xF) == 0) {
if (i > 0) {
char line[132];
snprintf(line, sizeof(line) - 1, "%-6s: %-49s | %-17s |", addr,
left, right);
SICSLogWriteTime(line, eOut, tp);
}
snprintf(addr, sizeof(addr) - 1, "0x%04X", i);
while (i >= 16 && i + 16 < count) {
if (memcmp(&text[i - 16], &text[i], 16) != 0)
break;
++duplicates;
i += 16;
}
if (duplicates > 0) {
if (duplicates > 1) {
char line[132];
snprintf(line, sizeof(line) - 1, "%-6s: ... (%d duplicates)",
addr, duplicates);
SICSLogWriteTime(line, eOut, tp);
} else {
char line[132];
snprintf(line, sizeof(line) - 1, "%-6s: %-49s | %-17s |", addr,
left, right);
SICSLogWriteTime(line, eOut, tp);
}
duplicates = 0;
}
snprintf(addr, sizeof(addr) - 1, "0x%04X", i);
lp = left;
rp = right;
}
*lp++ = hex[(text[i] >> 4) & 0xF];
*lp++ = hex[(text[i]) & 0xF];
*lp++ = ' ';
if (text[i] >= ' ' && text[i] <= '~')
*rp++ = text[i];
else
*rp++ = '.';
/* if we just did slot 7, insert an extra space */
if ((i & 0xF) == 7) {
*lp++ = ' ';
*rp++ = ' ';
}
*lp = *rp = '\0';
}
if (i > 0) {
char line[132];
snprintf(line, sizeof(line) - 1, "%-6s: %-49s | %-17s |", addr, left,
right);
SICSLogWriteTime(line, eOut, tp);
}
}
void SICSLogWriteHex(const char *text, int count, OutCode eOut)
{
SICSLogWriteHexTime(text, count, eOut, NULL);
}
void SICSLogTimePrintf(OutCode eOut, struct timeval *tp, const char *fmt,
...)
{
va_list ap;
char buf[256];
char *dyn;
unsigned int l;
int res;
va_start(ap, fmt);
l = vsnprintf(buf, sizeof buf, fmt, ap);
va_end(ap);
if (l >= sizeof buf) {
/* we have probably a C99 conforming snprintf and
need a larger buffer
*/
dyn = malloc(l + 1);
if (dyn != NULL) {
va_start(ap, fmt);
vsnprintf(dyn, l + 1, fmt, ap);
va_end(ap);
SICSLogWriteTime(dyn, eOut, tp);
free(dyn);
return;
}
}
SICSLogWriteTime(buf, eOut, tp);
return;
}
void SICSLogPrintf(OutCode eOut, const char *fmt, ...)
{
va_list ap;
char buf[256];
char *dyn;
unsigned int l;
int res;
va_start(ap, fmt);
l = vsnprintf(buf, sizeof buf, fmt, ap);
va_end(ap);
if (l >= sizeof buf) {
/* we have probably a C99 conforming snprintf and
need a larger buffer
*/
dyn = malloc(l + 1);
if (dyn != NULL) {
va_start(ap, fmt);
vsnprintf(dyn, l + 1, fmt, ap);
va_end(ap);
SICSLogWrite(dyn, eOut);
free(dyn);
return;
}
}
SICSLogWrite(buf, eOut);
return;
}

View File

@ -16,9 +16,25 @@
#define SICSLOG #define SICSLOG
#include "Scommon.h" #include "Scommon.h"
void SICSLogWrite(char *ptext, OutCode eOut); void SICSLogWrite(char *ptext, OutCode eOut);
void SICSLogEnable(int flag); void SICSLogWriteTime(char *ptext, OutCode eOut, struct timeval *tp);
int KillCapture(SConnection * pCon); void SICSLogWriteCode(char *ptext, OutCode eOut, char code);
void SICSLogWriteTimeCode(char *ptext, OutCode eOut, struct timeval *tp, char code);
int LogCapture(SConnection * pCon, SicsInterp * pInter, void *pData, void SICSLogWriteHex(const char *text, int count, OutCode eOut);
int argc, char *argv[]); void SICSLogWriteHexTime(const char *text, int count, OutCode eOut,
struct timeval *tp);
#if __GNUC__ > 2
#define G_GNUC_PRINTF( format_idx, arg_idx ) \
__attribute__((__format__ (__printf__, format_idx, arg_idx)))
#else
#define G_GNUC_PRINTF( format_idx, arg_idx )
#endif
void SICSLogPrintf(OutCode eOut, const char *fmt, ...) G_GNUC_PRINTF (2, 3);
void SICSLogTimePrintf(OutCode eOut, struct timeval *tp, const char *fmt,
...) G_GNUC_PRINTF (3, 4);
#undef G_GNUC_PRINTF
void SICSLogEnable(int flag);
typedef void (*pSICSLogHook)(const char *pText, OutCode eOut, void *pData);
char *AddSICSLogHook(pSICSLogHook func, const char *pCodes, void *pData);
char *RemSICSLogHook(void *pData);
unsigned int GetSICSLogHook(void *pData);
#endif #endif

View File

@ -90,7 +90,7 @@ static int SICSGetCommand(SConnection * pCon, SicsInterp * pSics, void *pData,
} }
} else { } else {
if(v.dataType == HIPTEXT && strstr(v.v.text,"ERROR") != NULL){ if(v.dataType == HIPTEXT && strstr(v.v.text,"ERROR") != NULL){
SCPrintf(pCon,eError,v.v.text); SCPrintf(pCon,eError,"%s",v.v.text);
} else { } else {
SCPrintf(pCon,eError,"ERROR: value for %s not found", argv[1]); SCPrintf(pCon,eError,"ERROR: value for %s not found", argv[1]);
} }
@ -153,6 +153,7 @@ static int InvokeSICSFunc(void *ms, void *userData)
SCsetMacro(pCon,0); SCsetMacro(pCon,0);
if(!status){ if(!status){
self->success = 0; self->success = 0;
SCDeleteConnection(pCon);
return MPSTOP; return MPSTOP;
} }
self->response = strdup(Tcl_GetStringResult(InterpGetTcl(pServ->pSics))); self->response = strdup(Tcl_GetStringResult(InterpGetTcl(pServ->pSics)));

4
sicsglobal.c Normal file
View File

@ -0,0 +1,4 @@
/***************************** Necessary Globals ****************************/
const char *argv0 = (void*) 0;
int isDuringInitialization = 1; /* gets set to zero after initialization */

6
sicsglobal.h Normal file
View File

@ -0,0 +1,6 @@
#ifndef SICSGLOBAL_H
#define SICSGLOBAL_H
extern const char *argv0;
extern int isDuringInitialization;
#endif

View File

@ -435,12 +435,12 @@ typedef struct {
int internalID; int internalID;
} HdbCBInfo; } HdbCBInfo;
static Protocol isJSON(SConnection * pCon) static Protocol isJSON(SConnection * pCon, int notify)
{ {
char proName[128]; char proName[128];
void *pData; void *pData;
if (SCinMacro(pCon)) { if (notify == 0 && SCinMacro(pCon)) {
return normal_protocol; return normal_protocol;
} }
pData = FindCommandData(pServ->pSics, "protocol", "Protocol"); pData = FindCommandData(pServ->pSics, "protocol", "Protocol");
@ -659,7 +659,7 @@ static hdbCallbackReturn SICSNotifyCallback(pHdb node, void *userData,
GetHdbPath(node,updatePath,sizeof(updatePath)); GetHdbPath(node,updatePath,sizeof(updatePath));
result = CreateDynString(128, 128); result = CreateDynString(128, 128);
if ((protocol = isJSON(cbInfo->pCon)) == 1) if ((protocol = isJSON(cbInfo->pCon, 1)) == 1)
outCode = eHdbEvent; outCode = eHdbEvent;
else else
outCode = eEvent; outCode = eEvent;
@ -688,8 +688,11 @@ static hdbCallbackReturn SICSNotifyCallback(pHdb node, void *userData,
} }
formatNameValue(protocol, updatePath, GetCharArray(printedData), result, formatNameValue(protocol, updatePath, GetCharArray(printedData), result,
mm->v->dataType); mm->v->dataType);
/* SCWrite(cbInfo->pCon, GetCharArray(result), outCode); */ #ifdef SITE_ANSTO
SCWrite(cbInfo->pCon, GetCharArray(result), outCode);
#else
SCPureSockWrite(cbInfo->pCon, GetCharArray(result), outCode); SCPureSockWrite(cbInfo->pCon, GetCharArray(result), outCode);
#endif
DeleteDynString(printedData); DeleteDynString(printedData);
} else { } else {
formatNameValue(protocol, updatePath, "!!datachange!!", result, HIPTEXT); formatNameValue(protocol, updatePath, "!!datachange!!", result, HIPTEXT);
@ -786,7 +789,7 @@ static hdbCallbackReturn TreeChangeCallback(pHdb node, void *userData,
return hdbAbort; return hdbAbort;
} }
path = GetHipadabaPath(node); path = GetHipadabaPath(node);
if ((protocol = isJSON(cbInfo->pCon)) == 1) if ((protocol = isJSON(cbInfo->pCon, 1)) == 1)
outCode = eHdbEvent; outCode = eHdbEvent;
else else
outCode = eEvent; outCode = eEvent;
@ -1540,7 +1543,7 @@ pHdb FindHdbParent(char *rootpath, char *relpath, char **namePtr,
} else { } else {
iret = snprintf(buffer, sizeof buffer, "%s/%s", rootpath, relpath); iret = snprintf(buffer, sizeof buffer, "%s/%s", rootpath, relpath);
} }
if (iret < 0 || iret >= sizeof(buffer)) { if (iret < 0 || iret >= (int) sizeof(buffer)) {
SCWrite(pCon, "ERROR: path too long", eError); SCWrite(pCon, "ERROR: path too long", eError);
return NULL; return NULL;
} }
@ -1652,7 +1655,7 @@ int GetHdbPath(pHdb nodeArg, char *path, size_t pathlen)
len = 0; len = 0;
for (node = nodeArg; node != NULL && node != root; node = node->mama) { for (node = nodeArg; node != NULL && node != root; node = node->mama) {
len += strlen(node->name) + 1; len += strlen(node->name) + 1;
if (len >= pathlen) if (len >= (int) pathlen)
return 0; /* buffer overflow (recursive path?) */ return 0; /* buffer overflow (recursive path?) */
parent = node; parent = node;
} }
@ -1669,7 +1672,7 @@ int GetHdbPath(pHdb nodeArg, char *path, size_t pathlen)
} }
l = strlen(sics); l = strlen(sics);
len += l; len += l;
if (len > pathlen) if (len > (int) pathlen)
return 0; /* buffer overflow */ return 0; /* buffer overflow */
strncpy(path, sics, l); strncpy(path, sics, l);
} }
@ -2336,6 +2339,71 @@ static int MakeHdbNode(SConnection * pCon, SicsInterp * pSics, void *pData,
return 1; return 1;
} }
/*--------------------------------------------------------------------------*/
static int MakeHdbScriptNode(SConnection * pCon, SicsInterp * pSics,
void *pData, int argc, char *argv[])
{
int type = 0, i, length = 0;
char *name = NULL;
pHdb parent = NULL;
pHdb child = NULL;
pHdb current = NULL;
char *urgv[] = { "5", NULL };
char driver[] = { "hdb" };
char buffer[512], buffer2[512];
if (!SCMatchRights(pCon, usMugger)) {
return 0;
}
if (argc < 5) {
SCWrite(pCon, "ERROR: not enough arguments to MakeHdbNode", eError);
return 0;
}
/*
* convert datatype
*/
strtolower(argv[4]);
type = convertHdbType(argv[4]);
if (type >= 7) {
SCWrite(pCon,
"ERROR: invalid type requested: none, int, float, text, intar, floatar, intvarar, floatvarar supported",
eError);
return 0;
}
if (type > 2) {
if (argc < 6) {
SCWrite(pCon, "ERROR: array length missing for array data type",
eError);
return 0;
} else {
length = atoi(argv[5]);
}
}
parent = FindHdbParent(NULL, argv[1], &name, pCon);
if (parent == NULL) {
return 0; /* error messages written inside FindHdbParent */
}
child = MakeSICSScriptPar(name, argv[3], argv[2],
makeHdbValue(type, length));
if (child == NULL) {
SCWrite(pCon, "ERROR: out of memory creating node", eError);
return 0;
}
AddHipadabaChild(parent, child, pCon);
/*
* have it polled automatically
*/
addPollObject(poller, pCon, GetHipadabaPath(child), driver, 1, urgv);
SCSendOK(pCon);
return 1;
}
/*------------------------------------------------------------------------------*/ /*------------------------------------------------------------------------------*/
static int isNodeProtected(pHdb node) static int isNodeProtected(pHdb node)
{ {
@ -2559,7 +2627,7 @@ static int ZipGetHdbNode(SConnection * pCon, SicsInterp * pSics,
SCWrite(pCon, "ERROR: out of memory formatting data", eError); SCWrite(pCon, "ERROR: out of memory formatting data", eError);
return 0; return 0;
} }
if ((protocol = isJSON(pCon)) == 1) if ((protocol = isJSON(pCon, 0)) == 1)
outCode = eHdbEvent; outCode = eHdbEvent;
else else
outCode = eValue; outCode = eValue;
@ -2604,7 +2672,7 @@ static int ZipReadHdbNode(SConnection * pCon, SicsInterp * pSics,
SCWrite(pCon, "ERROR: out of memory formatting data", eError); SCWrite(pCon, "ERROR: out of memory formatting data", eError);
return 0; return 0;
} }
if ((protocol = isJSON(pCon)) == 1) if ((protocol = isJSON(pCon,0)) == 1)
outCode = eHdbEvent; outCode = eHdbEvent;
else else
outCode = eValue; outCode = eValue;
@ -2715,13 +2783,17 @@ static int GetHdbNode(SConnection * pCon, SicsInterp * pSics, void *pData,
} }
} }
memset(&newValue, 0, sizeof(hdbValue)); memset(&newValue, 0, sizeof(hdbValue));
GetHipadabaPar(targetNode, &newValue, pCon); /* ffr XXX I expect if status=0 then we don't have a valid value
Original code was causing a segfault for hdb text nodes
*/
if (0 == GetHipadabaPar(targetNode, &newValue, pCon))
return 0;
parData = formatValue(newValue, targetNode); parData = formatValue(newValue, targetNode);
if (parData == NULL) { if (parData == NULL) {
SCWrite(pCon, "ERROR: out of memory formatting data", eError); SCWrite(pCon, "ERROR: out of memory formatting data", eError);
return 0; return 0;
} }
if ((protocol = isJSON(pCon)) == 1) if ((protocol = isJSON(pCon, 0)) == 1)
outCode = eHdbEvent; outCode = eHdbEvent;
else else
outCode = eValue; outCode = eValue;
@ -2759,13 +2831,14 @@ static int GetHdbVal(SConnection * pCon, SicsInterp * pSics, void *pData,
return 0; return 0;
} }
memset(&newValue, 0, sizeof(hdbValue)); memset(&newValue, 0, sizeof(hdbValue));
GetHipadabaPar(targetNode, &newValue, pCon); if (0 == GetHipadabaPar(targetNode, &newValue, pCon))
return 0;
parData = formatValue(newValue, targetNode); parData = formatValue(newValue, targetNode);
if (parData == NULL) { if (parData == NULL) {
SCWrite(pCon, "ERROR: out of memory formatting data", eError); SCWrite(pCon, "ERROR: out of memory formatting data", eError);
return 0; return 0;
} else { } else {
if ((protocol = isJSON(pCon)) == 1) if ((protocol = isJSON(pCon, 0)) == 1)
outCode = eHdbEvent; outCode = eHdbEvent;
else else
outCode = eValue; outCode = eValue;
@ -2777,6 +2850,37 @@ static int GetHdbVal(SConnection * pCon, SicsInterp * pSics, void *pData,
return 1; return 1;
} }
/*---------------------------------------------------------------------------*/
static int GetHdbValIgnoreError(
SConnection * pCon, SicsInterp * pSics, void *pData, int argc, char *argv[])
{
pHdb targetNode = NULL;
pDynString parData = NULL;
int protocol, outCode;
if (argc != 2) {
SCWrite(pCon, "ERROR: syntax must be: hvali <path>", eError);
return 0;
}
targetNode = FindHdbNode(NULL, argv[1], pCon);
if (targetNode == NULL) {
return 0;
}
parData = formatValue(targetNode->value, targetNode);
if (parData == NULL) {
SCWrite(pCon, "ERROR: out of memory formatting data", eError);
return 0;
}
if ((protocol = isJSON(pCon, 0)) == 1)
outCode = eHdbEvent;
else
outCode = eValue;
SCWrite(pCon, GetCharArray(parData), outCode);
DeleteDynString(parData);
return 1;
}
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
static int countChildren(pHdb node) static int countChildren(pHdb node)
{ {
@ -3071,7 +3175,7 @@ static int ListHdbNode(SConnection * pCon, SicsInterp * pSics, void *pData,
} else if (strcmp(argv[1], "-cli") == 0) { } else if (strcmp(argv[1], "-cli") == 0) {
listData = formatClientList(node); listData = formatClientList(node);
} else { } else {
if ((protocol = isJSON(pCon)) == 1) { if ((protocol = isJSON(pCon, 0)) == 1) {
listData = formatJSONList(node); listData = formatJSONList(node);
outCode = eHdbEvent; outCode = eHdbEvent;
} else { } else {
@ -3151,6 +3255,62 @@ static int RemoveHdbCallback(SConnection * pCon, SicsInterp * pSics,
return 1; return 1;
} }
/*---------------------------------------------------------------------------*/
static int LinkHdbNode(SConnection * pCon, SicsInterp * pSics, void *pData,
int argc, char *argv[])
{
pHdb node = NULL;
char buffer[256];
pObjectDescriptor pDes = NULL;
if (argc < 3) {
SCWrite(pCon, "ERROR: need path and object name to link", eError);
return 0;
}
if (!SCMatchRights(pCon, usMugger)) {
return 0;
}
node = GetHipadabaNode(root, argv[1]);
if (node == NULL) {
snprintf(buffer, 255, "ERROR: path %s NOT found!", argv[1]);
SCWrite(pCon, buffer, eError);
return 0;
}
pDes = FindCommandDescriptor(pSics, argv[2]);
if (pDes == NULL) {
snprintf(buffer, 255, "ERROR: failed to find object %s", argv[2]);
SCWrite(pCon, buffer, eError);
return 0;
}
if (pDes->parNode == NULL) {
snprintf(buffer, 255,
"ERROR: Object %s does not use Hipadaba natively and thus cannot be linked",
argv[2]);
SCWrite(pCon, buffer, eError);
return 0;
}
if (pDes->parNode->mama != NULL) {
snprintf(buffer, 255,
"ERROR: Object %s is already linked somewhere else", argv[2]);
SCWrite(pCon, buffer, eError);
return 0;
}
AddHipadabaChild(node, pDes->parNode, pCon);
if (argc > 3) {
if (pDes->parNode->name != NULL) {
free(pDes->parNode->name);
}
pDes->parNode->name = strdup(argv[3]);
}
SCSendOK(pCon);
return 1;
}
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
static int isArrayNode(pHdb node) static int isArrayNode(pHdb node)
{ {
@ -3599,9 +3759,9 @@ static hdbCallbackReturn CommandSetCallback(pHdb node, void *userData,
} }
current = current->next; current = current->next;
} }
SendHdbStatusMessage(node, "start"); // SendHdbStatusMessage(node,"start");
status = HDBInvoke(pCon, pServ->pSics, GetCharArray(cmd)); status = HDBInvoke(pCon, pServ->pSics, GetCharArray(cmd));
SendHdbStatusMessage(node, "stop"); // SendHdbStatusMessage(node,"stop");
DeleteDynString(cmd); DeleteDynString(cmd);
if (status == 1) { if (status == 1) {
return hdbContinue; return hdbContinue;
@ -3632,6 +3792,60 @@ static hdbCallbackReturn CommandGetCallback(pHdb node, void *userData,
return hdbContinue; return hdbContinue;
} }
/*--------------------------------------------------------------------------*/
static int SicsCommandNode(SConnection * pCon, SicsInterp * pSics,
void *pData, int argc, char *argv[])
{
char *name = NULL;
pHdbCallback kalle = NULL;
pHdb parent = NULL, node = NULL;
if (argc < 3) {
SCWrite(pCon, "ERROR: insufficent number of arguments to hcommand",
eError);
return 0;
}
if (!SCMatchRights(pCon, usMugger)) {
return 0;
}
parent = FindHdbParent(NULL, argv[1], &name, pCon);
if (parent == NULL) {
return 0; /* error message already written */
}
node = MakeHipadabaNode(name, HIPTEXT, 1);
if (node == NULL) {
SCWrite(pCon, "ERROR: out of memory in hcommand", eError);
return 0;
}
node->value.v.text = strdup(argv[2]);
node->value.arrayLength = strlen(argv[2]);
SetHdbProperty(node, "sicscommand", argv[2]);
// Set privillege of the node
if (argc > 3) {
SetHdbProperty(node, "priv", argv[3]);
}
kalle = MakeHipadabaCallback(CommandSetCallback, NULL, NULL);
if (kalle == NULL) {
SCWrite(pCon, "ERROR: out of memory in hcommand", eError);
return 0;
}
AppendHipadabaCallback(node, kalle);
kalle = MakeHipadabaCallback(CommandGetCallback, NULL, NULL);
if (kalle == NULL) {
SCWrite(pCon, "ERROR: out of memory in hcommand", eError);
return 0;
}
AppendHipadabaCallback(node, kalle);
AddHipadabaChild(parent, node, pCon);
SCSendOK(pCon);
return 1;
}
/*======================= Property Functions ================================*/ /*======================= Property Functions ================================*/
static int SetSICSHdbProperty(SConnection * pCon, SicsInterp * pSics, static int SetSICSHdbProperty(SConnection * pCon, SicsInterp * pSics,
void *pData, int argc, char *argv[]) void *pData, int argc, char *argv[])
@ -3681,6 +3895,30 @@ static int DelSICSHdbProperty(SConnection * pCon, SicsInterp * pSics,
return 1; return 1;
} }
/*--------------------------------------------------------------------------*/
static int HasSICSHdbProperty(SConnection * pCon, SicsInterp * pSics,
void *pData, int argc, char *argv[])
{
pHdb targetNode = NULL;
if (argc < 3) {
SCWrite(pCon, "ERROR: need path key as parameters", eError);
return 0;
}
targetNode = FindHdbNode(NULL, argv[1], pCon);
if (targetNode == NULL) {
SCWrite(pCon, "ERROR: node not found", eError);
return 0;
}
if (HasHdbProperty(targetNode, argv[2])) {
SCPrintf(pCon, eValue, "%s", "true");
return 1;
} else {
SCPrintf(pCon, eValue, "%s", "false");
return 1;
}
}
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
static int GetSICSHdbProperty(SConnection * pCon, SicsInterp * pSics, static int GetSICSHdbProperty(SConnection * pCon, SicsInterp * pSics,
void *pData, int argc, char *argv[]) void *pData, int argc, char *argv[])
@ -3741,10 +3979,18 @@ static int ListSICSHdbProperty(SConnection * pCon, SicsInterp * pSics,
char buffer[512]; char buffer[512];
const char *pKey = NULL; const char *pKey = NULL;
pDynString data = NULL; pDynString data = NULL;
int genTclList = 0;
if (argc < 2) { if (argc < 2) {
SCWrite(pCon, "ERROR: need path as parameter", eError); SCWrite(pCon, "ERROR: need path as parameter", eError);
return 0; return 0;
} else if (argc == 3) {
if (strncasecmp(argv[2], "tcl", 3) == 0)
genTclList = 1;
if (strncasecmp(argv[2], "tclesc", 6) == 0)
genTclList |= 2;
if (strncasecmp(argv[2], "tclnam", 6) == 0)
genTclList |= 4;
} }
targetNode = FindHdbNode(NULL, argv[1], pCon); targetNode = FindHdbNode(NULL, argv[1], pCon);
if (targetNode == NULL) { if (targetNode == NULL) {
@ -3759,9 +4005,24 @@ static int ListSICSHdbProperty(SConnection * pCon, SicsInterp * pSics,
InitHdbPropertySearch(targetNode); InitHdbPropertySearch(targetNode);
while ((pKey = GetNextHdbProperty(targetNode, buffer, 511)) != NULL) { while ((pKey = GetNextHdbProperty(targetNode, buffer, 511)) != NULL) {
DynStringConcat(data, (char *) pKey); DynStringConcat(data, (char *) pKey);
DynStringConcat(data, "="); if (genTclList) {
DynStringConcat(data, buffer); char *bp;
DynStringConcat(data, "\n"); DynStringConcatChar(data, ' ');
if (genTclList & 4)
continue;
DynStringConcatChar(data, '{');
for (bp = buffer; *bp; ++bp) {
if (genTclList & 2 && (*bp == '{' || *bp == '}'))
DynStringConcatChar(data, '\\');
DynStringConcatChar(data, *bp);
}
DynStringConcatChar(data, '}');
DynStringConcatChar(data, ' ');
} else {
DynStringConcat(data, "=");
DynStringConcat(data, buffer);
DynStringConcat(data, "\n");
}
} }
SCWrite(pCon, GetCharArray(data), eValue); SCWrite(pCon, GetCharArray(data), eValue);
DeleteDynString(data); DeleteDynString(data);
@ -3789,24 +4050,94 @@ static int CallNotify(SConnection * pCon, SicsInterp * pSics,
return 1; return 1;
} }
/*---------------------------------------------------------------------------*/ static int ANSTO_ListSICSHdbProperty(SConnection * pCon,
static pHdb matchHdbProp(pHdb root, char *propname, char *buffer) SicsInterp * pSics, void *pData,
int argc, char *argv[])
{ {
char value[1024]; pHdb targetNode = NULL;
char buffer[512], *globPtr = NULL;
int cmpSize = 0;
const char *pKey = NULL;
pDynString data = NULL;
if (argc < 3) {
SCWrite(pCon, "ERROR: need path and search string as parameters",
eError);
return 0;
}
targetNode = FindHdbNode(NULL, argv[1], pCon);
if (targetNode == NULL) {
SCWrite(pCon, "ERROR: node not found", eError);
return 0;
}
data = CreateDynString(64, 64);
if (data == NULL) {
SCWrite(pCon, "ERROR: out of memory in ListSICSHdbProperty", eError);
return 0;
}
InitHdbPropertySearch(targetNode);
/* Allow simple glob matches with '*' as a suffix
Eg hfindprop /hpath @*
*/
if ((globPtr = index(argv[2], '*')) != NULL) {
*globPtr = '\0';
}
cmpSize = strlen(argv[2]);
while ((pKey = GetNextHdbProperty(targetNode, buffer, 511)) != NULL) {
if (strncasecmp(argv[2], pKey, cmpSize) == 0) {
DynStringConcat(data, (char *) pKey);
DynStringConcat(data, " ");
DynStringConcat(data, buffer);
DynStringConcat(data, "\n");
}
}
SCWrite(pCon, GetCharArray(data), eValue);
DeleteDynString(data);
return 1;
}
/*---------------------------------------------------------------------------*/
static pHdb matchHdbProp(pHdb root, char *propname, char *buffer,
pDynString result, int invertmatch)
{
char value[1024], *path = NULL;
pHdb current = NULL, search; pHdb current = NULL, search;
memset(value, 0, 1024); memset(value, 0, 1024);
if (GetHdbProperty(root, propname, value, 1023) == 1) { if (strcmp(buffer, "*") == 0) {
if (GetHdbProperty(root, propname, value, 1023) == 1) {
if (!invertmatch) {
path = GetHipadabaPath(root);
DynStringConcat(result, path);
DynStringConcat(result, "\n");
free(path);
}
} else if (invertmatch) {
path = GetHipadabaPath(root);
DynStringConcat(result, path);
DynStringConcat(result, "\n");
free(path);
}
} else if (GetHdbProperty(root, propname, value, 1023) == 1) {
if (strstr(buffer, value) != NULL) { if (strstr(buffer, value) != NULL) {
return root; if (!invertmatch) {
path = GetHipadabaPath(root);
DynStringConcat(result, path);
DynStringConcat(result, "\n");
free(path);
}
} else if (invertmatch) {
path = GetHipadabaPath(root);
DynStringConcat(result, path);
DynStringConcat(result, "\n");
free(path);
} }
} }
current = root->child; current = root->child;
while (current != NULL) { while (current != NULL) {
search = matchHdbProp(current, propname, buffer); search =
if (search != NULL) { matchHdbProp(current, propname, buffer, result, invertmatch);
return search;
}
current = current->next; current = current->next;
} }
@ -3819,6 +4150,8 @@ static int MatchHdbProperty(SConnection * pCon, SicsInterp * pSics,
pHdb root = NULL; pHdb root = NULL;
pHdb foundNode = NULL; pHdb foundNode = NULL;
char buffer[1024], *path = NULL; char buffer[1024], *path = NULL;
int node = 1, prop = 2, propval = 3, invertmatch = 0;
pDynString matchList = NULL;
if (argc < 4) { if (argc < 4) {
SCWrite(pCon, SCWrite(pCon,
@ -3826,25 +4159,29 @@ static int MatchHdbProperty(SConnection * pCon, SicsInterp * pSics,
eError); eError);
return 0; return 0;
} }
if (argc >= 5) {
if (strcasecmp(argv[1], "invert") == 0) {
invertmatch = 1;
node++;
prop++;
propval++;
}
}
memset(buffer, 0, 1024); memset(buffer, 0, 1024);
Arg2Text(argc - 3, &argv[3], buffer, 1023); Arg2Text(argc - propval, &argv[propval], buffer, 1023);
root = GetHipadabaNode(GetHipadabaRoot(), argv[1]); root = GetHipadabaNode(GetHipadabaRoot(), argv[node]);
if (root == NULL) { if (root == NULL) {
SCWrite(pCon, "ERROR: start node for search not found", eError); SCWrite(pCon, "ERROR: start node for search not found", eError);
return 0; return 0;
} }
strtolower(argv[2]); strtolower(argv[prop]);
strtolower(buffer); strtolower(buffer);
foundNode = matchHdbProp(root, argv[2], buffer); matchList = CreateDynString(128, 128);
foundNode =
if (foundNode == NULL) { matchHdbProp(root, argv[prop], buffer, matchList, invertmatch);
SCWrite(pCon, "NONE", eValue); SCWrite(pCon, GetCharArray(matchList), eValue);
} else { DeleteDynString(matchList);
path = GetHipadabaPath(foundNode);
SCWrite(pCon, path, eValue);
free(path);
}
return 1; return 1;
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
@ -3953,7 +4290,9 @@ int InstallSICSHipadaba(SConnection * pCon, SicsInterp * pSics,
{ {
root = MakeHipadabaNode("/", HIPNONE, 0); root = MakeHipadabaNode("/", HIPNONE, 0);
AddCommand(pSics, "hmake", MakeHdbNode, NULL, NULL);
AddCommand(pSics, "hfactory", HdbNodeFactory, NULL, NULL); AddCommand(pSics, "hfactory", HdbNodeFactory, NULL, NULL);
AddCommand(pSics, "hmakescript", MakeHdbScriptNode, NULL, NULL);
AddCommand(pSics, "hattach", SICSHdbAdapter, NULL, NULL); AddCommand(pSics, "hattach", SICSHdbAdapter, NULL, NULL);
AddCommand(pSics, "hsubsamplehm", HdbSubSample, NULL, NULL); AddCommand(pSics, "hsubsamplehm", HdbSubSample, NULL, NULL);
AddCommand(pSics, "hdel", DeleteHdbNode, NULL, NULL); AddCommand(pSics, "hdel", DeleteHdbNode, NULL, NULL);
@ -3961,22 +4300,26 @@ int InstallSICSHipadaba(SConnection * pCon, SicsInterp * pSics,
AddCommand(pSics, "hupdate", UpdateHdbNode, NULL, NULL); AddCommand(pSics, "hupdate", UpdateHdbNode, NULL, NULL);
AddCommand(pSics, "hget", GetHdbNode, NULL, NULL); AddCommand(pSics, "hget", GetHdbNode, NULL, NULL);
AddCommand(pSics, "hval", GetHdbVal, NULL, NULL); AddCommand(pSics, "hval", GetHdbVal, NULL, NULL);
AddCommand(pSics, "hvali", GetHdbValIgnoreError, NULL, NULL);
AddCommand(pSics, "hzipget", ZipGetHdbNode, NULL, NULL); AddCommand(pSics, "hzipget", ZipGetHdbNode, NULL, NULL);
AddCommand(pSics, "hzipread", ZipReadHdbNode, NULL, NULL); AddCommand(pSics, "hzipread", ZipReadHdbNode, NULL, NULL);
AddCommand(pSics, "hbinread", BinReadHdbNode, NULL, NULL); AddCommand(pSics, "hbinread", BinReadHdbNode, NULL, NULL);
AddCommand(pSics, "hlist", ListHdbNode, NULL, NULL); AddCommand(pSics, "hlist", ListHdbNode, NULL, NULL);
AddCommand(pSics, "hnotify", AutoNotifyHdbNode, NULL, NULL); AddCommand(pSics, "hnotify", AutoNotifyHdbNode, NULL, NULL);
AddCommand(pSics, "hdelcb", RemoveHdbCallback, NULL, NULL); AddCommand(pSics, "hdelcb", RemoveHdbCallback, NULL, NULL);
AddCommand(pSics, "hlink", LinkHdbNode, NULL, NULL);
AddCommand(pSics, "hinfo", HdbNodeInfo, NULL, NULL); AddCommand(pSics, "hinfo", HdbNodeInfo, NULL, NULL);
/* AddCommand(pSics, "hval", HdbNodeVal, NULL, NULL);*/
AddCommand(pSics, "hchain", ChainHdbNode, NULL, NULL); AddCommand(pSics, "hchain", ChainHdbNode, NULL, NULL);
AddCommand(pSics, "hcommand", SicsCommandNode, NULL, NULL);
AddCommand(pSics, "harray", HdbArrayNode, NULL, NULL); AddCommand(pSics, "harray", HdbArrayNode, NULL, NULL);
AddCommand(pSics, "hsetprop", SetSICSHdbProperty, NULL, NULL); AddCommand(pSics, "hsetprop", SetSICSHdbProperty, NULL, NULL);
AddCommand(pSics, "hdelprop", DelSICSHdbProperty, NULL, NULL); AddCommand(pSics, "hdelprop", DelSICSHdbProperty, NULL, NULL);
AddCommand(pSics, "hgetprop", GetSICSHdbProperty, NULL, NULL); AddCommand(pSics, "hgetprop", GetSICSHdbProperty, NULL, NULL);
AddCommand(pSics, "hgetpropval", GetSICSHdbPropertyVal, NULL, NULL); AddCommand(pSics, "hgetpropval", GetSICSHdbPropertyVal, NULL, NULL);
AddCommand(pSics, "hmatchprop", MatchHdbProperty, NULL, NULL); AddCommand(pSics, "hmatchprop", MatchHdbProperty, NULL, NULL);
AddCommand(pSics, "hpropexists", HasSICSHdbProperty, NULL, NULL);
AddCommand(pSics, "hlistprop", ListSICSHdbProperty, NULL, NULL); AddCommand(pSics, "hlistprop", ListSICSHdbProperty, NULL, NULL);
AddCommand(pSics, "hfindprop", ANSTO_ListSICSHdbProperty, NULL, NULL);
AddCommand(pSics, "hcallnotify",CallNotify, NULL, NULL); AddCommand(pSics, "hcallnotify",CallNotify, NULL, NULL);
AddCommand(pSics, "haddcheck",AddCheck, NULL, NULL); AddCommand(pSics, "haddcheck",AddCheck, NULL, NULL);
AddCommand(pSics, "hscriptnotify",AddScriptNotify, NULL, NULL); AddCommand(pSics, "hscriptnotify",AddScriptNotify, NULL, NULL);

View File

@ -169,6 +169,18 @@ static int printObjectData(SConnection * pCon, pDummy obj, char *key)
} }
} }
static int existsObjectData(SConnection * pCon, pDummy obj, char *key)
{
char *ptr = NULL;
ptr = IFindOption(obj->pDescriptor->pKeys, key);
if (ptr != NULL)
SCPrintf(pCon, eValue, "%s", "true");
else
SCPrintf(pCon, eValue, "%s", "false");
return 1;
}
/*----------------------------------------------------------------- /*-----------------------------------------------------------------
* this function implements a set on top of a list. This means that * this function implements a set on top of a list. This means that
* the list is first searched for the occurence of name. name is only * the list is first searched for the occurence of name. name is only
@ -518,6 +530,21 @@ int SicsList(SConnection * pCon, SicsInterp * pSics, void *pData,
} }
} }
if (strcmp(argv[1], "exists") == 0) {
if (argc < 4) {
SCWrite(pCon, "ERROR: not enough arguments", eError);
return 0;
} else {
pCom = FindCommand(pSics, argv[2]);
if (pCom == NULL) {
SCWrite(pCon, "ERROR: Object doesn't exist", eError);
return 0;
} else
return existsObjectData(pCon, (pDummy) pCom->pData, argv[3]);
}
}
/* /*
* object properties * object properties
*/ */

View File

@ -477,7 +477,6 @@ int InvokeSICSOBJ(SConnection * pCon, SicsInterp * pSics, void *pData,
status = GetHdbProperty(parNode,"geterror",buffer,sizeof(buffer)); status = GetHdbProperty(parNode,"geterror",buffer,sizeof(buffer));
if (status == 1 && strstr(buffer,"none") == NULL){ if (status == 1 && strstr(buffer,"none") == NULL){
SCPrintf(pCon,eValue,"ERROR: %s on last read of %s", buffer, argv[0]); SCPrintf(pCon,eValue,"ERROR: %s on last read of %s", buffer, argv[0]);
SCPrintf(pCon,eValue,"%s = -99999", argv[0]);
return 0; return 0;
} }
status = GetHipadabaPar(parNode, &data, pCon); status = GetHipadabaPar(parNode, &data, pCon);

View File

@ -51,7 +51,8 @@ double DoubleTime(void)
{ {
struct timeval now; struct timeval now;
/* the resolution of this function is usec, if the machine supports this /* the resolution of this function is usec, if the machine supports this
and the mantissa of a double is 51 bits or more (31 for sec and 20 for mic$ and the mantissa of a double is 51 bits or more (31 bits for seconds
and 20 for microseconds)
*/ */
gettimeofday(&now, NULL); gettimeofday(&now, NULL);
return now.tv_sec + now.tv_usec / 1e6; return now.tv_sec + now.tv_usec / 1e6;

View File

@ -245,7 +245,7 @@ int VarSetFloat(pSicsVariable self, float fNew, int iUserRights)
if (self->iAccessCode < iUserRights) { if (self->iAccessCode < iUserRights) {
return 0; return 0;
} else { } else if (self->fVal != fNew) {
self->fVal = fNew; self->fVal = fNew;
InvokeCallBack(self->pCall, VALUECHANGE, self); InvokeCallBack(self->pCall, VALUECHANGE, self);
tracePar(self->name,"%f",fNew); tracePar(self->name,"%f",fNew);
@ -261,7 +261,7 @@ int VarSetInt(pSicsVariable self, int iNew, int iUserRights)
if (self->iAccessCode < iUserRights) { if (self->iAccessCode < iUserRights) {
return 0; return 0;
} else { } else if (self->iVal != iNew) {
self->iVal = iNew; self->iVal = iNew;
InvokeCallBack(self->pCall, VALUECHANGE, self); InvokeCallBack(self->pCall, VALUECHANGE, self);
tracePar(self->name,"%d",iNew); tracePar(self->name,"%d",iNew);
@ -277,7 +277,7 @@ int VarSetText(pSicsVariable self, char *pNew, int iUserRights)
if (self->iAccessCode < iUserRights) { if (self->iAccessCode < iUserRights) {
return 0; return 0;
} else { } else if (self->text && strcmp(self->text, pNew)) {
if (self->text) { if (self->text) {
free(self->text); free(self->text);
} }
@ -461,7 +461,7 @@ int VarWrapper(SConnection * pCon, SicsInterp * pInterp, void *pData,
return 1; return 1;
case veFloat: case veFloat:
VarGetFloat(pVar, &fVal); VarGetFloat(pVar, &fVal);
snprintf(pBueffel,sizeof(pBueffel)-1, "%s = %f", argv[0], fVal); snprintf(pBueffel,sizeof(pBueffel)-1, "%s = %#g", argv[0], fVal);
SCWrite(pCon, pBueffel, eValue); SCWrite(pCon, pBueffel, eValue);
DeleteTokenList(pList); DeleteTokenList(pList);
return 1; return 1;

View File

@ -244,6 +244,12 @@ static int SimSetPar(void *self, SConnection * pCon, char *name,
return 0; return 0;
} }
static int SimGetTextPar(void *pData, char *name, char *textPar)
{
snprintf(textPar, 8, "unknown");
return 1;
}
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
void KillSIM(void *pData) void KillSIM(void *pData)
{ {
@ -336,6 +342,7 @@ MotorDriver *CreateSIM(SConnection * pCon, int argc, char *argv[])
pDriv->fSpeed = .01; pDriv->fSpeed = .01;
pDriv->iTime = 0; pDriv->iTime = 0;
pDriv->KillPrivate = KillSIM; pDriv->KillPrivate = KillSIM;
pDriv->GetDriverTextPar = SimGetTextPar;
/* check for optional speed paramter */ /* check for optional speed paramter */
pCurrent = pCurrent->pNext; pCurrent = pCurrent->pNext;

View File

@ -85,6 +85,7 @@ int SimIdxRun();
* \param errCode pointer to an integer error code * \param errCode pointer to an integer error code
* \param error A text buffer to hold a description of the error * \param error A text buffer to hold a description of the error
* \param errLen The length of error * \param errLen The length of error
*/
void SimIdxGetError(int *errCode, char *error, int errLen); void SimIdxGetError(int *errCode, char *error, int errLen);
/** /**

View File

@ -56,7 +56,7 @@ char *pDeviceTypes[25] = {
"connection", "connection",
"crystalselector", "crystalselector",
"environment monitor", "environment monitor",
"environment controller", "environment_controller",
"gpib", "gpib",
"hklscan", "hklscan",
"hmcontrol", "hmcontrol",

View File

@ -450,7 +450,7 @@ static int SymRefCmd(pSICSOBJ self, SConnection * pCon, pHdb commandNode,
hkl[2] = equiv.l[i]; hkl[2] = equiv.l[i];
if (priv->diffractometer-> if (priv->diffractometer->
calculateSettings(priv->diffractometer, hkl, settings) == 1) { calculateSettings(priv->diffractometer, hkl, settings) == 1) {
snprintf(buffer, 512, "%d,%d,%d", equiv.h[i], equiv.k[i], snprintf(buffer, sizeof(buffer), "%d,%d,%d", equiv.h[i], equiv.k[i],
equiv.l[i]); equiv.l[i]);
SCWrite(pCon, buffer, eValue); SCWrite(pCon, buffer, eValue);
return 1; return 1;

322
stack_trace.c Normal file
View File

@ -0,0 +1,322 @@
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
#include <execinfo.h>
#include <signal.h>
#include <sys/wait.h>
#include <unistd.h>
#include <time.h>
#include <sys/time.h>
#include "dynstring.h"
#include "sics.h"
/*---------------------------------------------------------------------------*/
static const char* timestamp() {
static char ts[80];
int year, month, day;
int hour, min, sec, usec;
struct timeval tv;
struct tm *time;
gettimeofday(&tv, NULL);
time = localtime(&tv.tv_sec);
year = 1900 + time->tm_year;
month = time->tm_mon + 1;
day = time->tm_mday;
hour = time->tm_hour;
min = time->tm_min;
sec = time->tm_sec;
usec = (int) tv.tv_usec;
snprintf(ts, 80, "%04d%02d%02d%02d%02d%02d",
year, month, day, hour, min, sec);
return ts;
}
#ifdef SICS_HAS_BACKTRACE
void stack_trace_backtrace() {
void *array[STRACE_SIZE];
size_t stack_size;
size_t i;
char **strings;
char buffer[1024];
pDynString s = CreateDynString(1000, 100);
stack_size = backtrace(array, STRACE_SIZE);
strings = backtrace_symbols(array, stack_size);
for (i = 0; i < stack_size; ++i) {
snprintf(buffer, 1024, "%p: %s\n", array[i], strings[i]);
DynStringConcat(s, buffer);
}
free(strings);
SICSLogWrite(GetCharArray(s), eLogError);
DeleteDynString(s);
}
#endif
#ifdef SICS_HAS_BFD
#include <bfd.h>
#define STRACE_SIZE 64
/* globals retained across calls to resolve. */
static bfd* abfd = 0;
static asymbol **syms = 0;
static asection *text = 0;
static void resolve(void *address, char *buffer, int buf_len) {
if (!abfd) {
char ename[1024];
int l = readlink("/proc/self/exe",ename,sizeof(ename));
if (l == -1) {
perror("failed to find executable\n");
return;
}
ename[l] = 0;
bfd_init();
abfd = bfd_openr(ename, 0);
if (!abfd) {
perror("bfd_openr failed: ");
return;
}
/* oddly, this is required for it to work... */
bfd_check_format(abfd,bfd_object);
unsigned storage_needed = bfd_get_symtab_upper_bound(abfd);
syms = (asymbol **) malloc(storage_needed);
unsigned cSymbols = bfd_canonicalize_symtab(abfd, syms);
text = bfd_get_section_by_name(abfd, ".text");
}
long offset = ((long)address) - text->vma;
if (offset > 0) {
const char *file;
const char *func;
unsigned line;
if (bfd_find_nearest_line(abfd, text, syms, offset, &file, &func, &line) && file)
snprintf(buffer, buf_len, "file: %s, line: %u, func %s\n",file,line,func);
}
}
void stack_trace_bfd() {
void *array[STRACE_SIZE];
size_t stack_size;
size_t i;
char buffer[1024];
pDynString s = CreateDynString(1000, 100);
stack_size = backtrace(array, STRACE_SIZE);
for (i = 0; i < stack_size; ++i) {
resolve(array[i], buffer, 1024);
DynStringConcat(s, buffer);
}
SICSLogWrite(GetCharArray(s), eLogError);
DeleteDynString(s);
}
#endif
#ifdef SICS_HAS_GDB
void stack_trace_gdb() {
int pipefd[2];
char pid_buf[30];
sprintf(pid_buf, "%d", getpid());
char name_buf[512];
name_buf[readlink("/proc/self/exe", name_buf, 511)]=0;
if (pipe(pipefd) == -1) {
perror("pipe");
abort();
}
int child_pid = fork();
if (child_pid == -1) {
perror("fork");
abort();
}
if (!child_pid) {
close(pipefd[0]);
dup2(pipefd[1], 1); /* redirect stdout to pipe */
dup2(pipefd[1], 2); /* redirect stderr to pipe */
fprintf(stdout,"stack trace for %s pid=%s\n",name_buf,pid_buf);
fflush(stdout);
execlp("gdb", "gdb", "--batch", "-n", "-ex", "thread", "-ex", "bt", name_buf, pid_buf, NULL);
abort(); /* If gdb failed to start */
} else {
char buff;
pDynString s = CreateDynString(100, 100);
close(pipefd[1]);
while (read(pipefd[0], &buff, 1) > 0) {
DynStringConcatChar(s, buff);
}
SICSLogWrite(GetCharArray(s), eLogError);
DeleteDynString(s);
close(pipefd[0]);
waitpid(child_pid,NULL,0);
}
}
#endif
#ifdef SICS_HAS_ABORT
void stack_trace_abort() {
int child_pid = fork();
if (child_pid == -1) {
perror("fork");
abort();
}
if (!child_pid) {
/* Dump core */
abort();
} else {
waitpid(child_pid,NULL,0);
}
}
#endif
size_t get_size_of_files(char *glob) {
int pipefd[2];
if (pipe(pipefd) == -1) {
perror("pipe");
abort();
}
int child_pid = fork();
if (child_pid == -1) {
perror("fork");
abort();
}
if (!child_pid) {
char cmd[120];
close(pipefd[0]);
dup2(pipefd[1], 1); /* redirect stdout to pipe */
dup2(pipefd[1], 2); /* redirect stderr to pipe */
snprintf(cmd, sizeof(cmd)-1, "du -s %s", glob);
execlp("bash", "bash", "-c", cmd, NULL);
exit(0); /* If gdb failed to start */
} else {
size_t total_size = 0;
char buff;
pDynString s = CreateDynString(100, 100);
close(pipefd[1]);
while (read(pipefd[0], &buff, 1) > 0) {
DynStringConcatChar(s, buff);
if (buff == '\n') {
SICSLogWrite(GetCharArray(s), eLog);
int this_size = atoi(GetCharArray(s));
total_size += this_size;
DynStringClear(s);
}
}
if (GetDynStringLength(s) > 0)
SICSLogWrite(GetCharArray(s), eLogError);
DeleteDynString(s);
close(pipefd[0]);
waitpid(child_pid, NULL, 0);
SICSLogPrintf(eLog, "Total size of files \"%s\" is %ldK", glob, total_size);
return total_size;
}
}
void generate_stack_trace(int full, int dump) {
int pipefd[2];
char pid_buf[30];
sprintf(pid_buf, "%d", getpid());
char name_buf[512];
name_buf[readlink("/proc/self/exe", name_buf, 511)]=0;
if (pipe(pipefd) == -1) {
perror("pipe");
abort();
}
int child_pid = fork();
if (child_pid == -1) {
perror("fork");
abort();
}
if (!child_pid) {
char *bt;
close(pipefd[0]);
dup2(pipefd[1], 1); /* redirect stdout to pipe */
dup2(pipefd[1], 2); /* redirect stderr to pipe */
fprintf(stdout, "stack trace for %s pid=%s\n", name_buf, pid_buf);
fflush(stdout);
if (full)
bt = "bt full";
else
bt = "bt";
if (dump) {
char gen_buf[128];
snprintf(gen_buf, sizeof(gen_buf)-1, "generate-core-file /tmp/core.%s.%s", timestamp(), pid_buf);
execlp("gdb", "gdb", "--batch", "-n", "-ex", "thread", "-ex", bt, "-ex", gen_buf, name_buf, pid_buf, NULL);
} else {
execlp("gdb", "gdb", "--batch", "-n", "-ex", "thread", "-ex", bt, name_buf, pid_buf, NULL);
}
fprintf(stdout, "gdb failed to start for %s pid=%d\n", name_buf, getpid());
fflush(stdout);
abort(); /* If gdb failed to start */
} else {
char buff;
pDynString s = CreateDynString(100, 100);
close(pipefd[1]);
while (read(pipefd[0], &buff, 1) > 0) {
DynStringConcatChar(s, buff);
}
SICSLogWrite(GetCharArray(s), eLogError);
DeleteDynString(s);
close(pipefd[0]);
waitpid(child_pid, NULL, 0);
}
}
void stack_trace(int mode) {
switch (mode) {
case 0:
default:
#ifdef SICS_HAS_BACKTRACE
stack_trace_0();
#endif
break;
case 1:
#ifdef SICS_HAS_BFD
stack_trace_bfd();
#endif
break;
case 2:
#ifdef SICS_HAS_GDB
stack_trace_gdb();
#endif
break;
case 3:
#ifdef SICS_HAS_ABORT
stack_trace_abort();
#endif
break;
case 4:
generate_stack_trace(0, 0);
break;
case 5:
generate_stack_trace(0, 1);
break;
case 6:
generate_stack_trace(1, 0);
break;
case 7:
generate_stack_trace(1, 1);
break;
case 99:
get_size_of_files("/tmp/core.*");
break;
}
fflush(stdout);
}
/**
* \brief Tests the stack_trace facility
*/
int Ansto_Stack_Trace(SConnection *pCon, SicsInterp * pSics, void *pData, int argc, char *argv[]) {
int mode;
void stack_trace(int mode);
if (argc > 1)
mode = atoi(argv[1]);
else
mode = 1;
stack_trace(mode);
}

Some files were not shown because too many files have changed in this diff Show More