Merge branch 'develop' of ssh://gitorious.psi.ch/sinqdev/sics into develop

This commit is contained in:
2015-04-28 16:24:39 +02:00
95 changed files with 4011 additions and 1582 deletions

View File

@ -20,19 +20,25 @@
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include "nserver.h"
#include "servlog.h"
extern void KeepStartupCommands(); /* ofac.c */
/***************************** Necessary Globals ****************************/
IPair *pSICSOptions = NULL;
pServer pServ = NULL;
/* ========================= Less dreadful file statics =================== */
#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
initialisation file
@ -41,24 +47,52 @@ pServer pServ = NULL;
int main(int argc, char *argv[])
{
int iRet;
int daemonize = 0;
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 */
for (i = 1; i < argc; i++) {
if (strcmp(argv[i], "-nolog") == 0) {
for (i = firstArg; i < argc; i++) {
if (argv[i][0] == '-') {
if (strcasecmp(argv[i], "-nolog") == 0) {
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) {
file = argv[i];
} else {
fprintf(stderr, "Unrecognized argument ignored: %s\n", argv[i]);
}
}
if (file == NULL)
return usage(argv[0]);
iRet = InitServer(file, &pServ);
if (!iRet) {
printf("Unrecoverable error on server startup, exiting.........\n");
exit(1);
}
if (daemonize == 1)
daemon(1, 1);
RunServer(pServ);
@ -68,28 +102,3 @@ int main(int argc, char *argv[])
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 */
} OutCode;
const char* OutCodeToTxt(OutCode outcode);
const char* OutCodeToText(OutCode outcode);
int OutCodeFromText(const char *text, OutCode *outcode);
#include "interrupt.h"
/* define some user rights codes */

View File

@ -84,6 +84,8 @@ void AsconError(Ascon *a, char *msg, int errorno)
DynStringConcat(a->errmsg, " (");
DynStringConcat(a->errmsg, state);
DynStringConcat(a->errmsg, " state)");
DynStringConcat(a->errmsg, " on ");
DynStringConcat(a->errmsg, a->hostport);
} else {
DynStringConcat(a->errmsg, strerror(errorno));
DynStringConcat(a->errmsg, " (");
@ -91,6 +93,8 @@ void AsconError(Ascon *a, char *msg, int errorno)
DynStringConcat(a->errmsg, " state, ");
DynStringConcat(a->errmsg, msg);
DynStringConcat(a->errmsg, ")");
DynStringConcat(a->errmsg, " on ");
DynStringConcat(a->errmsg, a->hostport);
}
a->state = AsconFailed;
}
@ -818,7 +822,7 @@ char *AsconRead(Ascon * a)
{
if (a->noResponse) {
a->noResponse = 0;
return "";
return NULL;
}
if (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)
{
const char *term = "\r\n";
if (p->replyTerminator)
term = p->replyTerminator;
if (ch == term[txn->txn_state])
if (txn->txn_state == 0) {
int i;
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;
else
txn->txn_state = 0;
if (txn->inp_idx < txn->inp_len)
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)
txn->inp_buf[txn->inp_idx] = '\0';
return AQU_POP_CMD;
@ -64,10 +71,7 @@ int defaultPrepareTxn(pAsyncProtocol p, pAsyncTxn txn, const char *cmd,
term = p->sendTerminator;
state = 0;
for (i = 0; i < cmd_len; ++i) {
if (cmd[i] == 0x00) { /* end of transmission */
cmd_len = i;
break;
} else if (cmd[i] == term[state]) {
if (cmd[i] == term[state]) {
++state;
continue;
}
@ -100,14 +104,6 @@ int defaultPrepareTxn(pAsyncProtocol p, pAsyncTxn txn, const char *cmd,
if (txn->inp_buf != NULL) {
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_idx = 0;
txn->txn_state = 0;
@ -122,11 +118,15 @@ static void encodeTerminator(char *result, char *terminator)
{
if (terminator)
while (*terminator) {
if (*terminator <= 32 || *terminator >= 127) {
*result++ = '0';
*result++ = 'x';
*result++ = hex[(*terminator >> 4) & 0xF];
*result++ = hex[(*terminator) & 0xF];
++terminator;
} else {
*result++ = *terminator++;
}
}
*result = '\0';
return;
@ -208,7 +208,6 @@ int AsyncProtocolNoAction(SConnection * pCon, SicsInterp * pSics,
void *pData, int argc, char *argv[])
{
char line[132];
pAsyncProtocol self = (pAsyncProtocol) pData;
snprintf(line, 132, "%s does not understand %s", argv[0], argv[1]);
SCWrite(pCon, line, eError);
return 0;
@ -217,7 +216,6 @@ int AsyncProtocolNoAction(SConnection * pCon, SicsInterp * pSics,
int AsyncProtocolAction(SConnection * pCon, SicsInterp * pSics,
void *pData, int argc, char *argv[])
{
char line[132];
pAsyncProtocol self = (pAsyncProtocol) pData;
if (argc > 1) {
/* handle genecic parameters like terminators */
@ -240,22 +238,37 @@ int AsyncProtocolAction(SConnection * pCon, SicsInterp * pSics,
return 1;
} else if (strcasecmp(argv[1], "replyterminator") == 0) {
if (argc > 2) {
char *pPtr = decodeTerminator(argv[2]);
int i;
for (i = 0; i < 10; ++i)
if (self->replyTerminator[i]) {
free(self->replyTerminator[i]);
self->replyTerminator[i] = NULL;
}
for (i = 0; i < 10 && i < argc - 2; ++i) {
char* pPtr = decodeTerminator(argv[i + 2]);
if (pPtr) {
if (self->replyTerminator)
free(self->replyTerminator);
self->replyTerminator = pPtr;
self->replyTerminator[i] = pPtr;
}
}
SCSendOK(pCon);
} else {
int i;
char term[132];
char line[1024];
encodeTerminator(term, self->replyTerminator);
sprintf(line, "%s.replyTerminator = \"%s\"", argv[0], term);
term[0] = '\0';
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);
}
return 1;
}
} else if (strcasecmp(argv[1], "list") == 0) {
int ac = 2;
char *av[3] = { argv[0], 0, 0 };
@ -266,13 +279,13 @@ int AsyncProtocolAction(SConnection * pCon, SicsInterp * pSics,
return 1;
}
/* handle any other actions here */
}
return AsyncProtocolNoAction(pCon, pSics, pData, argc, argv);
}
void defaultKillPrivate(pAsyncProtocol p)
{
if (p->privateData) {
/* TODO: should we do anything? */
free(p->privateData);
}
}
@ -280,14 +293,23 @@ void defaultKillPrivate(pAsyncProtocol p)
void AsyncProtocolKill(void *pData)
{
pAsyncProtocol self = (pAsyncProtocol) pData;
if (self->pDes)
DeleteDescriptor(self->pDes);
if (self->sendTerminator != NULL)
free(self->sendTerminator);
if (self->replyTerminator != NULL)
free(self->replyTerminator);
int i;
if (self->killPrivate)
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,
@ -322,13 +344,14 @@ pAsyncProtocol AsyncProtocolCreate(SicsInterp * pSics,
AsyncProtocolKill(self);
return NULL;
}
self->protocolName = strdup(protocolName);
self->sendCommand = defaultSendCommand;
self->handleInput = defaultHandleInput;
self->handleEvent = defaultHandleEvent;
self->prepareTxn = defaultPrepareTxn;
self->killPrivate = defaultKillPrivate;
self->sendTerminator = strdup("\r\n");
self->replyTerminator = strdup("\r\n");
self->replyTerminator[0] = strdup("\r\n");
return self;
}

View File

@ -26,6 +26,12 @@ typedef enum {
ATX_DISCO = 3
} 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 {
pAsyncUnit unit; /**< unit that transaction is associated with */
int txn_state; /**< protocol handler transaction parse state */
@ -38,6 +44,8 @@ struct __async_txn {
int inp_len; /**< length of input buffer */
int inp_idx; /**< index of next character (number already received) */
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 */
/* The cntx field may be used by protocol handler from sendCommand
* as long as it is restored when response is complete
@ -51,7 +59,7 @@ struct __async_protocol {
pObjectDescriptor pDes;
char *protocolName;
char *sendTerminator;
char *replyTerminator;
char *replyTerminator[10];
void *privateData;
int (*sendCommand) (pAsyncProtocol p, pAsyncTxn txn);
int (*handleInput) (pAsyncProtocol p, pAsyncTxn txn, int ch);

View File

@ -15,11 +15,13 @@
#include <arpa/inet.h>
#include <netinet/tcp.h>
#include <netdb.h>
#include <ctype.h>
#include <stdarg.h>
#include <sics.h>
#include <rs232controller.h>
#include "network.h"
#include "asyncqueue.h"
#include "nwatch.h"
#include <stdbool.h>
typedef struct __async_command AQ_Cmd, *pAQ_Cmd;
@ -40,6 +42,9 @@ struct __AsyncUnit {
void *notify_cntx;
};
typedef enum { eAsyncIdle, eAsyncWaiting, eAsyncConnecting,
eAsyncConnected } AsyncState;
struct __AsyncQueue {
pObjectDescriptor pDes;
char *queue_name;
@ -48,6 +53,9 @@ struct __AsyncQueue {
int iDelay; /* intercommand delay in milliseconds */
int timeout;
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 */
int unit_count; /* number of units connected */
pAsyncUnit units; /* head of unit chain */
@ -56,12 +64,56 @@ struct __AsyncQueue {
pNWContext nw_ctx; /* NetWait context handle */
pNWTimer nw_tmr; /* NetWait timer handle */
mkChannel *pSock; /* socket address */
AsyncState state; /* Queue Connection State */
pAsyncProtocol protocol;
char *noreply_text;
int noreply_len;
void *context; /**< opaque caller queue context */
};
static pAsyncQueue queue_array[FD_SETSIZE];
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 ------------------------------------
CreateSocketAdress stolen from Tcl. Thanks to John Ousterhout
*/
@ -99,30 +151,175 @@ static int CreateSocketAdress(struct sockaddr_in *sockaddrPtr, /* Socket addres
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)
{
pAsyncUnit unit;
if (self->state != eAsyncConnected)
SICSLogPrintf(eStatus, "Function: %s:%s\n", self->queue_name,
__func__);
for (unit = self->units; unit; unit = unit->next)
if (unit->notify_func != NULL)
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)
{
int iRet;
int sock;
int flag = 1;
char line[132];
iRet = NETReconnect(self->pSock);
if (iRet <= 0) {
snprintf(line, 132, "Disconnect on AsyncQueue '%s'", self->queue_name);
SICSLogWrite(line, eStatus);
if (self->state != eAsyncConnected)
SICSLogPrintf(eStatus, "Function: %s:%s\n", self->queue_name,
__func__);
/*
* 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_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;
}
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;
}
@ -135,7 +332,11 @@ static int StartCommand(pAsyncQueue self)
{
pAQ_Cmd myCmd = self->command_head;
mkChannel *sock = self->pSock;
int iRet = 0;
if (self->state != eAsyncConnected)
SICSLogPrintf(eStatus, "Function: %s:%s\n", self->queue_name,
__func__);
if (myCmd == NULL)
return OKOK;
@ -143,7 +344,7 @@ static int StartCommand(pAsyncQueue self)
* Remove any old command timeout timer
*/
if (self->nw_tmr)
NetWatchRemoveTimer(self->nw_tmr);
AQ_ClearTimer(self);
/*
* Implement the inter-command delay
@ -164,7 +365,7 @@ static int StartCommand(pAsyncQueue self)
int delay = when.tv_sec - now.tv_sec;
delay *= 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;
}
}
@ -172,33 +373,56 @@ static int StartCommand(pAsyncQueue self)
/*
* Discard any input before sending command
*/
if (NETAvailable(sock, 0)) {
while (NETAvailable(sock, 0)) {
/* TODO: handle unsolicited input */
char reply[1];
int iRet;
iRet = NETRead(sock, reply, 1, 0);
char reply[128];
iRet = NETRead(sock, reply, 128, 0);
if (iRet < 0) { /* EOF */
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;
} 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
*/
if (myCmd->timeout > 0)
NetWatchRegisterTimer(&self->nw_tmr, myCmd->timeout,
AQ_SetTimer(self, myCmd->timeout,
CommandTimeout, self);
else
NetWatchRegisterTimer(&self->nw_tmr, 30000, CommandTimeout, self);
AQ_SetTimer(self, 30000, CommandTimeout, self);
myCmd->active = 1;
return self->protocol->sendCommand(self->protocol, myCmd->tran);
return iRet;
}
static int QueCommandHead(pAsyncQueue self, pAQ_Cmd cmd)
@ -239,13 +463,17 @@ static int QueCommand(pAsyncQueue self, pAQ_Cmd cmd)
self->command_tail = cmd;
return 1;
}
static int PopCommand(pAsyncQueue self)
{
pAQ_Cmd myCmd = self->command_head;
if (self->nw_tmr)
NetWatchRemoveTimer(self->nw_tmr);
self->nw_tmr = 0;
AQ_ClearTimer(self);
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
*/
@ -255,10 +483,7 @@ static int PopCommand(pAsyncQueue self)
StartCommand(self);
} else
self->command_head = self->command_tail = NULL;
free(myCmd->tran->out_buf);
free(myCmd->tran->inp_buf);
free(myCmd->tran);
free(myCmd);
free_command(myCmd);
return 1;
}
@ -267,6 +492,13 @@ static int CommandTimeout(void *cntx, int mode)
pAsyncQueue self = (pAsyncQueue) cntx;
pAQ_Cmd myCmd = self->command_head;
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) {
--myCmd->retries;
StartCommand(self);
@ -276,8 +508,6 @@ static int CommandTimeout(void *cntx, int mode)
self->protocol->handleEvent(self->protocol, myCmd->tran,
AQU_TIMEOUT);
if (iRet == AQU_POP_CMD) {
if (myCmd->tran->handleResponse)
myCmd->tran->handleResponse(myCmd->tran);
PopCommand(self); /* remove command */
} else if (iRet == AQU_RETRY_CMD)
StartCommand(self); /* restart command */
@ -290,6 +520,9 @@ static int CommandTimeout(void *cntx, int mode)
static int DelayedStart(void *cntx, int mode)
{
pAsyncQueue self = (pAsyncQueue) cntx;
if (self->state != eAsyncConnected)
SICSLogPrintf(eStatus, "Function: %s:%s\n", self->queue_name,
__func__);
self->nw_tmr = 0;
StartCommand(self);
return 1;
@ -299,27 +532,18 @@ static int MyCallback(void *context, int mode)
{
pAsyncQueue self = (pAsyncQueue) context;
if (self->state != eAsyncConnected)
SICSLogPrintf(eStatus, "Function: %s:%s\n", self->queue_name,
__func__);
if (mode & nwatch_read) {
int iRet;
char reply[1];
char reply[100];
iRet = NETRead(self->pSock, reply, 1, 0);
/* printf(" iRet, char = %d, %d\n", iRet, (int)reply[0]); */
iRet = NETRead(self->pSock, reply, 100, 0);
if (iRet < 0) { /* EOF */
iRet = AQ_Reconnect(self);
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);
}
if (iRet <= 0)
return iRet;
}
/* restart the command */
StartCommand(self);
return 1;
@ -327,22 +551,74 @@ static int MyCallback(void *context, int mode)
if (iRet == 0) { /* TODO: timeout or error */
return 0;
} else {
int nchars = iRet;
int i = 0;
pAQ_Cmd myCmd = self->command_head;
if (myCmd) {
for (i = 0; i < nchars; ++i) {
iRet =
self->protocol->handleInput(self->protocol, myCmd->tran,
reply[0]);
reply[i] & 0xFF);
if (iRet == 0 || iRet == AQU_POP_CMD) { /* end of command */
if (myCmd->tran->handleResponse)
myCmd->tran->handleResponse(myCmd->tran);
if (self->trace) {
struct timeval tv;
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);
} else if (iRet < 0) /* TODO: error */
;
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 {
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 */
}
}
}
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;
}
@ -395,20 +671,43 @@ pAsyncTxn AsyncUnitPrepareTxn(pAsyncUnit unit,
myTxn = (pAsyncTxn) malloc(sizeof(AsyncTxn));
if (myTxn == NULL) {
SICSLogWrite("ERROR: Out of memory in AsyncUnitPrepareTxn", eError);
return 0;
return NULL;
}
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) {
int iRet;
myTxn->inp_len = rsp_len; /* allowing protocol to change it */
iRet =
unit->queue->protocol->prepareTxn(unit->queue->protocol, myTxn,
command, cmd_len, rsp_len);
if (iRet == 0) {
free(myTxn);
return NULL;
}
rsp_len = myTxn->inp_len; /* allowed protocol to change it */
} else {
myTxn->out_buf = (char *) malloc(cmd_len + 5);
if (myTxn->out_buf == NULL) {
SICSLogWrite("ERROR: Out of memory in AsyncUnitPrepareTxn", eError);
free(myTxn);
return 0;
return NULL;
}
memcpy(myTxn->out_buf, command, cmd_len);
myTxn->out_len = cmd_len;
@ -423,15 +722,12 @@ pAsyncTxn AsyncUnitPrepareTxn(pAsyncUnit unit,
if (rsp_len == 0)
myTxn->inp_buf = NULL;
else {
if (myTxn->inp_buf != NULL) {
free(myTxn->inp_buf);
}
myTxn->inp_buf = malloc(rsp_len + 1);
if (myTxn->inp_buf == NULL) {
SICSLogWrite("ERROR: Out of memory in AsyncUnitPrepareTxn", eError);
free(myTxn->out_buf);
free(myTxn);
return 0;
return NULL;
}
memset(myTxn->inp_buf, 0, rsp_len + 1);
}
@ -458,6 +754,7 @@ int AsyncUnitSendTxn(pAsyncUnit unit,
typedef struct txn_s {
char *transReply;
int transWait;
int respLen;
} TXN, *pTXN;
/**
@ -469,30 +766,33 @@ static int TransCallback(pAsyncTxn pCmd)
int resp_len = pCmd->inp_idx;
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);
self->transReply[resp_len] = '\0';
} else
self->transReply[0] = '\0';
if (pCmd->txn_status == ATX_TIMEOUT)
self->transWait = -1;
} else {
memcpy(self->transReply, resp, resp_len);
self->transReply[resp_len] = '\0';
else
self->transWait = 0;
}
return 0;
}
int AsyncUnitTransact(pAsyncUnit unit,
const char *command, int cmd_len,
char *response, int rsp_len)
char *response, int *rsp_len)
{
TXN txn;
assert(unit);
txn.transReply = response;
txn.respLen = *rsp_len;
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)
TaskYield(pServ->pTasker);
*rsp_len = txn.respLen;
if (txn.transWait < 0)
return txn.transWait;
return 1;
@ -505,6 +805,13 @@ int AsyncUnitWrite(pAsyncUnit unit, void *buffer, int buflen)
assert(unit);
assert(unit->queue);
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);
iRet = NETWrite(sock, buffer, buflen);
/* TODO handle errors */
@ -593,24 +900,75 @@ int AsyncQueueAction(SConnection * pCon, SicsInterp * pSics,
char line[132];
pAsyncQueue self = (pAsyncQueue) pData;
if (argc > 1) {
if (strcasecmp("send", argv[1]) == 0) {
if (strcasecmp("send", argv[1]) == 0 || strcasecmp("transact", argv[1]) == 0) {
AsyncUnit myUnit;
char cmd[10240];
char rsp[10240];
int idx = 0;
int i, j;
int i, j, len;
cmd[0] = '\0';
/* Managers only */
if (!SCMatchRights(pCon, usMugger))
return 0;
for (i = 2; i < argc; ++i) {
j = snprintf(&cmd[idx], 10240 - idx, "%s%s",
(i > 2) ? " " : "", argv[i]);
if (j < 0)
if (idx >= 10240)
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));
myUnit.queue = self;
AsyncUnitTransact(&myUnit, cmd, idx, rsp, 10240);
SCWrite(pCon, rsp, eValue);
len = 10240;
(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;
}
if (strcasecmp(argv[1], "reconnect") == 0) {
@ -627,7 +985,7 @@ int AsyncQueueAction(SConnection * pCon, SicsInterp * pSics,
SCWrite(pCon, line, eError);
return 0;
} else {
if (delay < 0 || delay > 30000) {
if (delay < 0 || delay > 300000) {
snprintf(line, 132, "Value out of range: %d", delay);
SCWrite(pCon, line, eError);
return 0;
@ -692,6 +1050,85 @@ int AsyncQueueAction(SConnection * pCon, SicsInterp * pSics,
}
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]);
SCWrite(pCon, line, eError);
@ -741,6 +1178,7 @@ static pAsyncQueue AQ_Create(const char *host, const char *port)
}
if (self == NULL) {
/* TODO: if channel (self->pSock) is NULL we haven't connected yet, do it later */
if (channel == NULL)
return NULL;
@ -760,6 +1198,15 @@ static pAsyncQueue AQ_Create(const char *host, const char *port)
if (i == queue_index)
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;
}
@ -769,6 +1216,7 @@ static int AQ_Init(pAsyncQueue self)
if (self->nw_ctx == NULL)
NetWatchRegisterCallback(&self->nw_ctx,
self->pSock->sockid, MyCallback, self);
NetWatchSetMode(self->nw_ctx, nwatch_write | nwatch_read);
return 1;
}
@ -784,7 +1232,7 @@ static void AQ_Kill(void *pData)
if (self->nw_ctx)
NetWatchRemoveCallback(self->nw_ctx);
if (self->nw_tmr)
NetWatchRemoveTimer(self->nw_tmr);
AQ_ClearTimer(self);
if (self->queue_name)
free(self->queue_name);
NETClosePort(self->pSock);
@ -979,3 +1427,31 @@ pAsyncUnit AsyncUnitFromQueue(pAsyncQueue queue)
result->queue = queue;
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"
#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;
@ -28,7 +22,7 @@ typedef struct __AsyncQueue AsyncQueue, *pAsyncQueue;
*/
int AsyncUnitCreate(const char *queueName, pAsyncUnit * unit);
/** \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
*/
pAsyncUnit AsyncUnitFromQueue(pAsyncQueue queue);
@ -39,6 +33,10 @@ pAsyncUnit AsyncUnitFromQueue(pAsyncQueue queue);
* \param port number or service name on the target host
* \param unit pointer to the AsyncUnit created on positive return
* \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,
const char *port, pAsyncUnit * unit);
@ -98,11 +96,12 @@ int AsyncUnitSendTxn(pAsyncUnit unit,
* \param cmd_len length of data in command
* \param responseHandler function to handle the response
* \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,
const char *command, int cmd_len,
char *response, int rsp_len);
char *response, int *rsp_len);
/** \brief write to the AsyncQueue file descriptor
*
@ -182,4 +181,16 @@ int AsyncQueueFactory(SConnection * pCon, SicsInterp * pSics,
int AsyncQueueAction(SConnection * pCon, SicsInterp * pSics,
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 */

View File

@ -397,14 +397,20 @@ void ANETprocess(void)
{
int i, status, count = 0, socke = 0, length;
fd_set readMask, writeMask;
struct timeval tmo = { 0, 20 };
struct timeval tmo = { 0, 10000 };
FD_ZERO(&readMask);
FD_ZERO(&writeMask);
for (i = 0; i < noConnections; i++) {
socke = connections[i].socket;
FD_SET(socke, &readMask);
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) {
count = socke;
}

View File

@ -271,6 +271,36 @@ int RemoveCallback2(pICallBack self, void *pUserData)
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)
{

View File

@ -174,7 +174,7 @@ static void KillAdapter(void *pData)
if (self->pInt)
free(self->pInt);
if (self->pParName);
if (self->pParName)
free(self->pParName);
free(self);

View File

@ -538,7 +538,7 @@ int CommandLog(SConnection * pCon, SicsInterp * pSics, void *pData,
if (iCompact > 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;
} else if (strcmp(argv[1], "close") == 0) { /* close command */
fclose(fd);

View File

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

View File

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

View File

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

276
conman.c
View File

@ -73,6 +73,7 @@
#include "statusfile.h"
#include "sicshipadaba.h"
#include "protocol.h"
#include "sicsvar.h"
/*
#define UUDEB 1
define UUDEB , for buffer writing for checking encoding */
@ -81,6 +82,13 @@ extern pServer pServ;
#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 */
#define MAXSTACK 1024
@ -108,6 +116,24 @@ struct SCStore {
long macroStack;
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)
{
@ -650,7 +676,7 @@ int SCPrintf(SConnection * self, int iOut, char *fmt, ...)
va_list ap;
char buf[256];
char *dyn;
int l;
unsigned int l;
int res;
va_start(ap, fmt);
@ -779,6 +805,64 @@ static int testAndWriteSocket(SConnection * pCon, char *buffer, int iOut)
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)
{
@ -793,7 +877,11 @@ int SCNormalWrite(SConnection * self, char *buffer, int iOut)
}
/* log it for any case */
#if 0
SICSLogWrite(buffer, iOut);
#else
testAndWriteSICSLog(self, buffer, iOut);
#endif
testAndWriteCommandLog(self, buffer, iOut);
@ -2137,6 +2225,190 @@ int ConSicsAction(SConnection * pCon, SicsInterp * pSics, void *pData,
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)
{
@ -2207,7 +2479,7 @@ int SCTaskFunction(void *pData)
pPassword = strtok(NULL, " \t\r\n");
iRet = IsValidUser(pUser, pPassword);
if (iRet >= 0) {
SCWrite(self, "Login OK", eError);
SCWrite(self, "Login OK", eLog);
self->iLogin = 1;
SCSetRights(self, iRet);
pHost[0] = '\0';

View File

@ -92,7 +92,14 @@ SConnection *GetSendingConnection(void);
/* ***************************** I/O ************************************** */
void SCSetOutputClass(SConnection * self, int iClass);
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 SCPrompt(SConnection * pCon, char *pPrompt, char *pResult, int iLen);
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);
/* check for lock */
if (self->iLock) {
return 0;
}
/* check Size */
if (self->iCount >= self->iMaxSize) {
return 0;
@ -138,11 +134,6 @@ int CostaBottom(pCosta self, char *pCommand)
int iRet, iRes = 1;
assert(self);
/* check for lock */
if (self->iLock) {
return 0;
}
/* do not want 0 commands */
if (strlen(pCommand) < 1) {
return 1;
@ -187,3 +178,10 @@ void CostaUnlock(pCosta self)
{
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 CostaUnlock(pCosta self);
int CostaLocked(pCosta self);
#endif

View File

@ -61,6 +61,7 @@ pCounterDriver CreateCounterDriver(char *name, char *type)
pRes->fPreset = 1000.;
pRes->fTime = 0.;
pRes->iNoOfMonitors = 0;
pRes->iControlMonitor = 0;
pRes->iPause = 0;
pRes->Start = NULL;
pRes->GetStatus = NULL;

View File

@ -42,6 +42,7 @@ typedef struct __COUNTER {
float fLastCurrent;
float fTime;
int iNoOfMonitors;
int iControlMonitor;
long lCounts[MAXCOUNT];
int iPause;
int iErrorCode;

View File

@ -571,6 +571,21 @@ static int GetNMonitorImpl(pCounter self)
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
extern float nintf(float f);
#endif
@ -643,7 +658,7 @@ static long GetCountsImpl(pCounter self, SConnection * pCon)
if (!self->isUpToDate) {
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)
@ -658,7 +673,7 @@ static long GetMonitorImpl(pCounter self, int iNum, SConnection * pCon)
if (!self->isUpToDate) {
self->pCountInt->TransferData(self, pCon);
}
if ((iNum < 0) || (iNum > self->pDriv->iNoOfMonitors)) {
if ((iNum < 0) || (iNum >= self->pDriv->iNoOfMonitors)) {
return -1L;
} else {
return self->pDriv->lCounts[iNum];
@ -832,6 +847,8 @@ int CountAction(SConnection * pCon, SicsInterp * pSics, void *pData,
{"getnmon", 0, {0, 0}},
{"state", 0, {0, 0}},
{"error", 0, {0, 0}},
{"getchannel",0,{0}},
{"setchannel",1,{FUPAINT}},
{"countstatus", 0, {0, 0}}
};
char *pMode[] = {
@ -849,7 +866,7 @@ int CountAction(SConnection * pCon, SicsInterp * pSics, void *pData,
argtolower(argc, argv);
argx = &argv[1];
iRet =
EvaluateFuPa((pFuncTemplate) & ActionTemplate, 26, argc - 1, argx,
EvaluateFuPa((pFuncTemplate) & ActionTemplate, 28, argc - 1, argx,
&PaRes);
if (iRet < 0) {
snprintf(pBueffel, 255,"%s", PaRes.pError);
@ -958,7 +975,7 @@ int CountAction(SConnection * pCon, SicsInterp * pSics, void *pData,
SCSendOK(pCon);
return 1;
case 11: /* status */
case 25:
case 27:
self->pCountInt->TransferData(self, pCon);
if (GetCounterMode(self) == ePreset) {
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,
PaRes.Arg[1].iVal, &fVal);
if (iRet == 1) {
snprintf(pBueffel,255, "%s.%s %d = %f", argv[0], PaRes.Arg[0].text,
PaRes.Arg[1].iVal, fVal);
snprintf(pBueffel,255, "%s.%s %s = %f", argv[0], PaRes.Arg[0].text,
PaRes.Arg[1].text, fVal);
SCWrite(pCon, pBueffel, eValue);
return 1;
} else {
@ -1172,6 +1189,19 @@ int CountAction(SConnection * pCon, SicsInterp * pSics, void *pData,
SCWrite(pCon, pBueffel, eValue);
return 1;
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:
assert(0); /* internal error */
}

View File

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

View File

@ -177,10 +177,23 @@ static int SecCtrCheckStatus(void *pData, SConnection *pCon)
ReleaseHdbValue(&v);
node = GetHipadabaNode(self->pDes->parNode,"control");
if(self->getMode(self) == eTimer){
node = GetHipadabaNode(self->pDes->parNode,"time");
assert(node != NULL);
GetHipadabaPar(node,&v,pCon);
fControl = v.v.doubleValue;
} else {
node = GetHipadabaNode(self->pDes->parNode,"values");
assert(node != NULL);
/*
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");
assert(node != NULL);
GetHipadabaPar(node,&v,pCon);

View File

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

View File

@ -15,6 +15,8 @@
#include "drive.h"
#include "counter.h"
extern double DoubleTime(void);
#define DIFFMONITOR 0
#define SKIP 1
@ -121,6 +123,57 @@ int DiffScanWrapper(SConnection * pCon, SicsInterp * pSics, void *pData,
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
*/
@ -180,6 +233,7 @@ static int StartDiffScan(pDiffScan self, pScanData pScan,
self->scaleMonitor = (int) ObVal(self->parArray, DIFFMONITOR);
self->normalizationScale = -1;
pScan->iCounts = 0;
pScan->iNP = 0;
/*
get variable
@ -190,6 +244,7 @@ static int StartDiffScan(pDiffScan self, pScanData pScan,
SCWrite(pCon, "ERROR: cannot access scan variable", eError);
return 0;
}
InitScanVar(pVar);
/*
drive to start position
@ -250,6 +305,9 @@ static float normalizeEntry(pCountEntry pCount, pCountEntry last,
pCount->Monitors[i] =
(pCount->Monitors[i] - last->Monitors[i]) * fScale;
}
fScale = pCount->fTime - last->fTime;
if (fScale > 0)
value /= fScale;
return value;
}
@ -271,12 +329,26 @@ static int DiffScanTask(void *pData)
char pBueffel[255];
long rawCount, rawMon;
CountEntry rawCopy;
double now;
pDiffScan self = (pDiffScan) pData;
/*
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->skipCount > self->skip) {
self->skipCount = 0;
@ -285,6 +357,7 @@ static int DiffScanTask(void *pData)
return 1;
}
}
#endif
/*
read motor status
@ -327,7 +400,7 @@ static int DiffScanTask(void *pData)
traceSys("diffscan","START:normalizing on %d, scale monitor is %d",
self->normalizationScale, self->scaleMonitor);
} 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);
SCWrite(self->scanObject->pCon,"WARNING: Skipping first point because of low count rate", eWarning);
return finish;
@ -336,7 +409,7 @@ static int DiffScanTask(void *pData)
if (data->Monitors[self->scaleMonitor - 1] -
self->last.Monitors[self->scaleMonitor - 1] < 5) {
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]);
}
rawCount = data->lCount;
@ -350,12 +423,25 @@ static int DiffScanTask(void *pData)
/*
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,
fPos, countValue, rawCount, rawMon);
fPos, countValue, rawCount, rawMon, data->fTime);
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);
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);
/*
@ -385,6 +471,7 @@ int RunDiffScan(pDiffScan self, pScanData pScan,
if (StartDiffScan(self, pScan, pCon, fEnd) != 1) {
return 0;
}
self->last_report_time = DoubleTime();
InvokeCallBack(self->scanObject->pCall, SCANSTART, self->scanObject);

View File

@ -12,6 +12,9 @@
#include "obpar.h"
#include "scan.h"
#include "scan.i"
#include "sicsvar.h"
#include "hipadaba.h"
#include "sicshipadaba.h"
typedef struct {
pObjectDescriptor pDes;
@ -22,6 +25,9 @@ typedef struct {
int skip;
int skipCount;
pScanData scanObject;
double last_report_time;
pSicsVariable sicsvar;
pHdb hdbnode;
} 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
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
you rather sooner then later.
you rather sooner than later.
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
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
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}

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
which must be present for any motor driver. Then there are fields
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
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
@ -122,12 +122,12 @@ creates a simulation motor driver.
\end{description}
\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
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
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
whole night and subsequently broke a clutch.
Motors are represented by the
@ -164,7 +164,7 @@ object.
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
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.
\begin{description}
\item[int MotorGetPar(pMotor self, char *name, float *fVal)] retrieves the

12
drive.c
View File

@ -39,6 +39,7 @@
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include <math.h>
#include "fortify.h"
#include "sics.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 */
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);
return 0;
}
@ -301,7 +302,7 @@ int DriveWrapper(SConnection * pCon, SicsInterp * pSics, void *pData,
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) {
if (argv[i + 1] == NULL) {
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);
if (iRet == TCL_ERROR) {
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;
}
iRet = Start2Run(pCon, pSics, argv[i], RUNDRIVE, dTarget);

View File

@ -35,7 +35,14 @@ typedef struct {
* \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
* \param list the error list

View File

@ -178,7 +178,7 @@ static pDynString findBlockEnd(pExeBuf self)
{
pDynString command = NULL;
char *buffer = NULL;
int i;
int i, j;
assert(self);
@ -190,7 +190,8 @@ static pDynString findBlockEnd(pExeBuf self)
if (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]);
if (buffer[i] == '\n') {
self->lineno++;

View File

@ -138,6 +138,9 @@ void DeleteNodeData(pHdb node)
if (node->name != NULL) {
free(node->name);
}
if (node->path != NULL) {
free(node->path);
}
ReleaseHdbValue(&node->value);
node->magic = 000000;
@ -601,7 +604,7 @@ int compareHdbValue(hdbValue v1, hdbValue v2)
}
break;
case HIPFLOAT:
if (ABS(v1.v.doubleValue - v2.v.doubleValue) < .01) {
if (ABS(v1.v.doubleValue - v2.v.doubleValue) < .0001) { /* DFC */
return 1;
} else {
return 0;
@ -895,6 +898,7 @@ char *GetHipadabaPath(pHdb node)
strcat(pPtr, "/");
strcat(pPtr, nodeStack[i]->name);
}
node->path = 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)
{

View File

@ -72,6 +72,7 @@ typedef struct __hipadaba {
struct __hipadaba *next;
struct __hdbcallback *callBackChain;
char *name;
char *path;
hdbValue value;
int iprotected;
pStringDict properties;
@ -446,6 +447,13 @@ void SetHdbProperty(pHdb node, char *key, char *value);
* @param len The length of value
* @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);
/**
* get the value of a property

View File

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

View File

@ -109,6 +109,8 @@
void *pUserData, KillFuncIT pKill);
int RemoveCallback(pICallBack pInterface, long iID);
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 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);
if (NULL == Tmp) {
Tmp = ListControl[List].first;
NODE_FREE(Tmp); /* no need to cause memory leaks */
ListControl[List].first = NULL; /* or other errors */
return ERR_MEMORY; /* even if we're in trouble ... */

View File

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

View File

@ -118,6 +118,11 @@ static int LogSetup(SConnection * pCon, SicsInterp * pSics, void *pData,
LoggerChange(logger, period, name);
} else {
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);
SetHdbProperty(node, "logger_name", name);
cb = MakeHipadabaCallback(LoggerUpdateCallback, logger,

View File

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

View File

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

View File

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

View File

@ -30,9 +30,9 @@
*
* 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
* - Fixed state monitor eclipse commit problems. Siiiiiiiggggghhhhhh!
*
@ -87,7 +87,7 @@
*******************************************************************************/
#ifndef MCSTAS_R_H
#define MCSTAS_R_H "$Revision: 1.1 $"
#define MCSTAS_R_H "$Revision$"
#include <math.h>
#include <string.h>
@ -569,9 +569,9 @@ void mcsiminfo_close(void);
*
* 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
* - Fixed state monitor eclipse commit problems. Siiiiiiiggggghhhhhh!
*
@ -4356,9 +4356,9 @@ MCNUM mccDet9_zmax;
* %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
* - Fixed state monitor eclipse commit problems. Siiiiiiiggggghhhhhh!
*
@ -4433,9 +4433,9 @@ static void Table_Stat(t_Table *mc_rt_Table);
* Usage: within SHARE
* %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
* - 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
* %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
* - Fixed state monitor eclipse commit problems. Siiiiiiiggggghhhhhh!
*
@ -5460,9 +5460,9 @@ void Monitor_nD_McDisplay(MonitornD_Defines_type *,
* Usage: within SHARE
* %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
* - Fixed state monitor eclipse commit problems. Siiiiiiiggggghhhhhh!
*

View File

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

41
motor.c
View File

@ -81,6 +81,8 @@
#define IGNOREFAULT 10
#define MOVECOUNT 11
extern double DoubleTime(void);
/*-------------------------------------------------------------------------*/
static void SetMotorError(pMotor self, char *text)
{
@ -351,8 +353,9 @@ static int checkPosition(pMotor self, SConnection * pCon)
SCWrite(pCon, pBueffel, eWarning);
return HWFault;
}
snprintf(pBueffel, 131, "WARNING: %s off position by %f",
self->name, absf(fHard - self->fTarget));
snprintf(pBueffel, 131, "WARNING: %s off position by %f%s",
self->name, absf(fHard - self->fTarget),
self->fTarget > fHard ? "-" : "");
SCWrite(pCon, pBueffel, eLog);
status = statusRunTo(self, pCon);
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;
MotorGetSoftPosition(self, pCon, &sCall.fVal);
sCall.pName = self->name;
self->fPosition = sCall.fVal;
self->fPosition = sCall.fVal;
if (self->moving) {
InvokeCallBack(self->pCall, MOTDRIVE, &sCall); /* send also very last position */
InvokeCallBack(self->pCall, MOTEND, &sCall);
tracePar(self->name,"%f",sCall.fVal);
}
self->moving = 0;
self->running = 0;
}
@ -474,13 +480,15 @@ static void handleMoveCallback(pMotor self, SConnection * pCon)
{
MotCallback sCall;
self->posCount++;
if (self->posCount >= ObVal(self->ParArray, MOVECOUNT)) {
double current_time, skip_time;
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);
sCall.pName = self->name;
InvokeCallBack(self->pCall, MOTDRIVE, &sCall);
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->retryCount = 0;
self->stopped = 0;
self->moving = 1;
self->fTarget = fHard;
InvokeCallBack(self->pCall, HDBVAL, self);
self->last_report_time = 0.0;
self->posCount = 0;
iRet = self->pDriver->RunTo(self->pDriver, fHard);
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, POSCOUNT, "maxretry", 3.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));
pM->fTarget = pM->fPosition;
pM->endScriptID = 0;
@ -1226,6 +1236,20 @@ static int EndScriptCallback(int iEvent, void *pEvent, void *pUser)
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:
@ -1321,13 +1345,14 @@ int MotorAction(SConnection * pCon, SicsInterp * pSics, void *pData,
}
pMoti->lastValue = fValue;
RemoveCallbackUsr(self->pCall, InterestCallback, CheckMotiMatch, pCon); /* only this one */
lID = RegisterCallback(self->pCall, MOTDRIVE, InterestCallback,
pMoti, KillInfo);
DeleteTokenList(pList);
SCSendOK(pCon);
return 1;
} else if (strcmp(pCurrent->text, "uninterest") == 0) {
RemoveCallbackCon(self->pCall, pCon);
RemoveCallbackUsr(self->pCall, InterestCallback, CheckMotiMatch, pCon); /* only this one */
SCSendOK(pCon);
DeleteTokenList(pList);
return 1;

View File

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

View File

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

View File

@ -21,10 +21,10 @@
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 <assert.h>

View File

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

32
nread.c
View File

@ -294,7 +294,12 @@ static int NetReadRead(pNetRead self, pNetItem pItem)
*pEnd = '\0';
/* do we have something in hold ? */
if (strlen(pItem->pHold) > 0) {
strlcat(pItem->pHold, pPtr,511);
strlcat(pItem->pHold, pPtr, 511);
/* DFC locking for protocol zero only */
if (pItem->pCon->iProtocolID == 0 &&
CostaLocked(pItem->pCon->pStack))
iStat = 0;
else
iStat = CostaTop(pItem->pCon->pStack, pItem->pHold);
if (!iStat) {
SCWrite(pItem->pCon, "ERROR: Busy", eError);
@ -302,6 +307,11 @@ static int NetReadRead(pNetRead self, pNetItem pItem)
pItem->pHold[0] = '\0';
} else {
/* no, normal command */
/* DFC locking for protocol zero only */
if (pItem->pCon->iProtocolID == 0 &&
CostaLocked(pItem->pCon->pStack))
iStat = 0;
else
iStat = CostaTop(pItem->pCon->pStack, pPtr);
if (!iStat) {
SCWrite(pItem->pCon, "ERROR: Busy", eError);
@ -487,6 +497,11 @@ static int TelnetRead(pNetRead self, pNetItem pItem)
break;
case '\r':
case '\n':
/* DFC locking for protocol zero only */
if (pItem->pCon->iProtocolID == 0 &&
CostaLocked(pItem->pCon->pStack))
iStat = 0;
else
iStat = CostaTop(pItem->pCon->pStack, pItem->pHold);
/* printf("%s\n",pItem->pHold); */
if (!iStat) {
@ -1027,6 +1042,7 @@ static int testAndInvokeInterrupt(pCommandCBData self, int handle)
snprintf(buffer, 512, "INTERRUPT %d issued on sock %d",
iInt, handle);
WriteToCommandLog("SYS>", buffer);
SICSLogWrite(buffer, eInternal);
if (iInt == eEndServer) {
TaskStop(pServ->pTasker);
}
@ -1060,8 +1076,10 @@ static int CommandDataCB(int handle, void *userData)
if (pPtr[i] == '\r' || pPtr[i] == '\n') {
self->state = SKIPTERM;
if (!testAndInvokeInterrupt(self, handle)) {
status =
CostaTop(self->pCon->pStack, GetCharArray(self->command));
if (self->pCon->iProtocolID == 0 && CostaLocked(self->pCon->pStack))
status = 0;
else
status = CostaTop(self->pCon->pStack, GetCharArray(self->command));
if (!status) {
SCWrite(self->pCon, "ERROR: Busy", eError);
}
@ -1162,8 +1180,10 @@ static int ANETTelnetProcess(int handle, void *usData)
case '\r':
case '\n':
if (!testAndInvokeInterrupt(self, handle)) {
status =
CostaTop(self->pCon->pStack, GetCharArray(self->command));
if (self->pCon->iProtocolID == 0 && CostaLocked(self->pCon->pStack))
status = 0;
else
status = CostaTop(self->pCon->pStack, GetCharArray(self->command));
if (!status) {
SCWrite(self->pCon, "ERROR: Busy", eError);
}
@ -1334,7 +1354,7 @@ static int TelnetAcceptCB(int handle, void *userData)
static void NREADlog(int level, char *txt, void *userData)
{
traceSys("anet",txt);
puts(txt);
SICSLogWrite(txt, (level == ANETERROR) ? eLogError : eLog);
}
/*------------------------------------------------------------------------------------*/

View File

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

110
nwatch.c
View File

@ -18,8 +18,8 @@
#include <sys/time.h>
#include "fortify.h"
#include "nwatch.h"
#include "sics.h"
#include "uselect.h"
#include "sics.h"
#define NWMAGIC 51966
@ -36,14 +36,12 @@ typedef struct __netwatcher_s {
/* Singleton pattern */
static pNetWatch instance = NULL;
static int NetWatchTask(void *pData);
/**
* \brief Initialises the Net Watcher singleton and starts the task
*
* \return 1=success, 0=failure
*/
int NetWatchInit(void)
static pNetWatch NetWatchGetInstance(void)
{
/*
* If the singleton has not yet been created, do so now
@ -54,9 +52,8 @@ int NetWatchInit(void)
return 0;
memset(instance, 0, sizeof(NetWatch));
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 */
pNWCallback func; /* function to call */
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 */
} NWTimer;
static pNWTimer activeTimer = NULL;
/*
* \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) {
self->tq_head = self->tq_tail = handle;
handle->next = NULL;
handle->vrfy = NWMAGIC;
return 1;
}
/* 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 = handle;
handle->next = NULL;
handle->vrfy = NWMAGIC;
return 1;
}
/* 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->next = self->tq_head;
self->tq_head = handle;
handle->vrfy = NWMAGIC;
return 1;
} else {
/* 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 */
handle->next = pNxt->next;
pNxt->next = handle;
}
handle->vrfy = NWMAGIC;
return 1;
}
return 0;
}
/*
@ -125,6 +130,7 @@ static int NetWatchTimerInsQue(pNetWatch self, pNWTimer handle)
*/
static int NetWatchTimerRemQue(pNetWatch self, pNWTimer handle)
{
assert(handle->vrfy == NWMAGIC);
/* handle the case of first and possibly only */
if (handle == self->tq_head) {
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)
self->tq_tail = pNxt;
}
handle->vrfy = 0;
return 1;
}
int NetWatchRegisterTimer(pNWTimer * handle, int mSec,
pNWCallback callback, void *context)
{
pNetWatch self = instance;
assert(callback);
pNetWatch self = NetWatchGetInstance();
if (!self || self->lMagic != NWMAGIC)
return 0;
pNWTimer pNew = (pNWTimer) malloc(sizeof(NWTimer));
@ -165,10 +173,10 @@ int NetWatchRegisterTimer(pNWTimer * handle, int mSec,
pNew->tv.tv_sec++;
pNew->tv.tv_usec -= 1000000;
}
pNew->msec = mSec;
pNew->tick = 0;
pNew->func = callback;
pNew->cntx = context;
pNew->vrfy = NWMAGIC;
NetWatchTimerInsQue(self, pNew);
*handle = pNew;
return 1;
@ -178,6 +186,7 @@ int NetWatchRegisterTimerPeriodic(pNWTimer * handle, int mSecInitial,
int mSecPeriod, pNWCallback callback,
void *context)
{
assert(callback);
if (NetWatchRegisterTimer(handle, mSecInitial, callback, context)) {
pNWTimer pNew = *handle;
if (pNew == NULL)
@ -189,16 +198,36 @@ int NetWatchRegisterTimerPeriodic(pNWTimer * handle, int mSecInitial,
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)
{
if (handle == NULL || handle->vrfy != NWMAGIC)
if (handle == NULL
|| (handle->vrfy != NWMAGIC && handle->vrfy != ~NWMAGIC))
return 0;
return handle->tick;
}
int NetWatchSetTimerPeriod(pNWTimer handle, int mSecPeriod)
{
if (handle == NULL || handle->vrfy != NWMAGIC)
if (handle == NULL
|| (handle->vrfy != NWMAGIC && handle->vrfy != ~NWMAGIC))
return 0;
handle->tick = mSecPeriod;
return 1;
@ -206,9 +235,11 @@ int NetWatchSetTimerPeriod(pNWTimer handle, int mSecPeriod)
int NetWatchRemoveTimer(pNWTimer handle)
{
pNetWatch self = instance;
pNetWatch self = NetWatchGetInstance();
if (!self || self->lMagic != NWMAGIC)
return 0;
if (handle == NULL || handle->vrfy != NWMAGIC)
return 0;
NetWatchTimerRemQue(self, handle);
handle->vrfy = 0;
free(handle);
@ -239,35 +270,10 @@ static int NetWatchContextInsQue(pNetWatch self, pNWContext handle)
self->cq_tail->next = handle;
self->cq_tail = handle;
}
handle->vrfy = NWMAGIC;
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
@ -286,18 +292,18 @@ static void NetWatchContextPrgQue(pNetWatch self)
free(tmp);
}
pNxt = self->cq_head;
while (pNxt) {
if (pNxt->next && pNxt->next->sock < 0) {
while (pNxt && pNxt->next) {
if (pNxt->next->sock < 0) {
pNWContext tmp = NULL;
tmp = pNxt->next;
pNxt->next = pNxt->next->next;
tmp->vrfy = 0;
free(tmp);
continue;
}
pNxt = pNxt->next;
}
/* if the queue is empty clear the tail */
if (self->cq_head == NULL)
/* if the queue is empty then pNxt is NULL else pNxt points to the tail */
self->cq_tail = pNxt;
self->nInvalid = 0;
return;
@ -306,8 +312,9 @@ static void NetWatchContextPrgQue(pNetWatch self)
int NetWatchRegisterCallback(pNWContext * handle, int iSocket,
pNWCallback callback, void *context)
{
assert(callback);
pNWContext pNew = NULL;
pNetWatch self = instance;
pNetWatch self = NetWatchGetInstance();
if (!self || self->lMagic != NWMAGIC)
return 0;
if (iSocket < 0 || iSocket > 65535)
@ -320,7 +327,6 @@ int NetWatchRegisterCallback(pNWContext * handle, int iSocket,
pNew->mode = nwatch_read;
pNew->func = callback;
pNew->cntx = context;
pNew->vrfy = NWMAGIC;
*handle = pNew;
NetWatchContextInsQue(self, pNew);
return 1;
@ -328,13 +334,16 @@ int NetWatchRegisterCallback(pNWContext * handle, int iSocket,
int NetWatchRemoveCallback(pNWContext handle)
{
pNetWatch self = instance;
pNetWatch self = NetWatchGetInstance();
if (handle == NULL || handle->vrfy != NWMAGIC)
return 0;
if (!self || self->lMagic != NWMAGIC)
return 0;
/* mark as invalid */
handle->sock = -1;
/* increment count of invalid */
self->nInvalid++;
/* leave for garbage collection */
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)
{
@ -367,7 +377,7 @@ int NetWatchTask(void *pData)
int iCount;
/* Check the singleton */
self = (pNetWatch) instance;
self = NetWatchGetInstance();
if (!self || self->lMagic != NWMAGIC)
return 0;
@ -430,7 +440,11 @@ int NetWatchTask(void *pData)
break;
}
NetWatchTimerRemQue(self, pNew);
activeTimer = pNew;
activeTimer->vrfy = ~NWMAGIC;
iStatus = pNew->func(pNew->cntx, 0);
activeTimer->vrfy = 0;
activeTimer = NULL;
/*
* If this is a recurrent timer and the function
* 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
* writeable and invokes callbacks. It also provides a timer mechanism.
@ -7,8 +7,8 @@
* Douglas Clowes, February 2007
*
*/
#ifndef SICSNETWATCHER
#define SICSNETWATCHER
#ifndef NETWATCH_H
#define NETWATCH_H
#define nwatch_read 1
#define nwatch_write 2
@ -53,6 +53,10 @@ int NetWatchRegisterTimerPeriodic(pNWTimer * handle, int mSecInitial,
int mSecPeriod, pNWCallback callback,
void *context);
pNWTimer NetWatchGetActiveTimer(void);
int NetWatchGetTimerDelay(pNWTimer handle);
int NetWatchGetTimerInitial(pNWTimer handle);
int NetWatchGetTimerPeriod(pNWTimer handle);
int NetWatchSetTimerPeriod(pNWTimer handle, int mSecPeriod);
/**
@ -103,4 +107,4 @@ int NetWatchGetMode(pNWContext handle);
*/
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;
int iToken;
int iMode;
char pAlias[132];
char pDefinition[1024]; /* this is > 10 lines of definition */
char pWord[132];
char pAlias[1024];
char pDefinition[8192]; /* this is > 10 lines of definition */
char pWord[1024];
assert(pBuffer);
assert(pDict);
@ -1490,6 +1490,126 @@ NXstatus NXDinfoalias(NXhandle hFil, NXdict dict, char *pAlias, int *rank,
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,
char *pTarget, char *pVictim)

View File

@ -462,6 +462,7 @@ static void putHdb(SConnection * pCon, SicsInterp * pSics, pNXScript self,
hdbValue v;
float fVal, *floatAr = NULL;
int i;
int start[5], size[5];
if (argc < 3) {
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);
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) {
case HIPNONE:
return;
@ -922,6 +940,7 @@ static void putHistogramMemoryChunked(SConnection * pCon,
}
/*----------------------------------------------------------------------*/
#define HANUM 3
static void putSlab(SConnection * pCon, SicsInterp * pSics, pNXScript self,
int argc, char *argv[])
{
@ -1986,6 +2005,35 @@ static void makeLink(SConnection * pCon, SicsInterp * pSics,
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,
char *argv[])
@ -2095,6 +2143,10 @@ int NXScriptAction(SConnection * pCon, SicsInterp * pSics, void *pData,
makeLink(pCon, pSics, self, argc, argv);
return 1;
}
if (strcmp(argv[1], "makenamedlink") == 0) {
makeNamedLink(pCon, pSics, self, argc, argv);
return 1;
}
return 1;
}

View File

@ -176,7 +176,9 @@ int ObParSet(ObPar * self, char *obname, char *name, float fVal,
/* are we running? */
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);
return 0;
}

9
ofac.c
View File

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

View File

@ -171,7 +171,7 @@ static int ContextDo(SConnection * pCon, SicsInterp * pSics, void *pData,
comCon = SCCopyConnection(pCon);
if (comCon == NULL) {
SCWrite(pCon, "EROOR: out of memory in contextdo", eError);
SCWrite(pCon, "ERROR: out of memory in contextdo", eError);
return 0;
}
status = Tcl_GetInt(pSics->pTcl, argv[1], &comCon->transID);

View File

@ -201,7 +201,7 @@ static int StatCmd(pSICSOBJ self, SConnection *pCon, pHdb commandNode,
}
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;
}

View File

@ -404,6 +404,7 @@ static char *SctActionHandler(void *actionData, char *lastReply,
char *errorScript = NULL;
char *send = NULL;
int i;
int j;
SConnection *con;
char eprop[80];
char msg[1024];
@ -431,22 +432,23 @@ static char *SctActionHandler(void *actionData, char *lastReply,
* property result to the data from the device. Read this now and
* print it if diagnostics is required.
*/
SetProp(node, controller->node, "result", lastReply);
script = NULL;
if (!commError && controller->verbose && lastReply != NULL
&& *lastReply != '\0') {
if (lastReply != NULL) {
SetProp(node, controller->node, "result", lastReply);
if (*lastReply != '\0') {
if (!commError && controller->verbose) {
SCPrintf(con, eLog, "%6.3f reply : %s\n", secondsOfMinute(), lastReply);
}
if(!commError && controller->fd != NULL && lastReply != NULL && *lastReply != '\0'){
if(!commError && controller->fd != NULL) {
fprintf(controller->fd, "%6.3f reply : %s\n", secondsOfMinute(), lastReply);
}
if(lastReply != NULL && *lastReply != '\0'){
if(data != NULL && data->controller != NULL){
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
@ -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",
data->name, origScript, path, result);
} 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);
}
}
@ -529,6 +531,21 @@ static char *SctActionHandler(void *actionData, char *lastReply,
if (strcasecmp(data->name, "read") == 0) {
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);
blank = strchr(origScript, ' ');
if (blank != NULL) {
@ -544,6 +561,21 @@ static char *SctActionHandler(void *actionData, char *lastReply,
}
cnt++;
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);
send = NULL;
free(script);
@ -951,12 +983,15 @@ int SctAddPollNode(SctController * controller, Hdb * node, double interval,
{
SctData *data;
hdbCallback *cb;
char nodePath[512], info[1024];
if (!FindHdbCallbackData(node, controller)) {
cb = MakeHipadabaCallback(SctMainCallback, controller, NULL);
assert(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));

View File

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

515
servlog.c
View File

@ -47,16 +47,18 @@
- NETWrites log message (if enabled) before attempt to write to file
- uses OpenVerifyLogFile helper function (removed duplicate code)
-----------------------------------------------------------------------------*/
#include <stdarg.h>
#include "fortify.h"
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include <ctype.h>
#include <time.h>
#include <sys/time.h>
#include <strlutil.h>
#include "ifile.h"
#include "conman.h"
#include "servlog.h"
#include "network.h"
@ -69,24 +71,142 @@
this the following code is necessary.
*/
typedef struct __LogLog {
SConnection *pCon;
OutCode iOut;
int iAllFlag;
pSICSLogHook pFunc;
void *pData;
unsigned int code_bits;
struct __LogLog *pNext;
struct __LogLog *pPrevious;
} CaptureEntry, *pCaptureEntry;
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;
/* find first */
pCurrent = pCapture;
while (pCurrent != NULL) {
if (pCon == pCurrent->pCon) {
if (pData == pCurrent->pData) {
/* relink */
if (pCurrent->pPrevious) {
pCurrent->pPrevious->pNext = pCurrent->pNext;
@ -104,88 +224,27 @@ int KillCapture(SConnection * pCon)
pCurrent = pCurrent->pNext;
}
}
return 1;
return NULL;
}
/* ------------------------------------------------------------------------
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[])
/* Return bitmask of any and all hooks with this pData */
unsigned int GetSICSLogHook(void *pData)
{
pCaptureEntry pNew = NULL;
char pBueffel[512];
int i;
pCaptureEntry pCurrent, pTemp;
unsigned int code_bits = 0;
/* check no af args */
if (argc < 2) {
snprintf(pBueffel,sizeof(pBueffel)-1, "Insufficient number of argumenst to %s", argv[0]);
SCWrite(pCon, pBueffel, eError);
return 0;
/* find first */
pCurrent = pCapture;
while (pCurrent != NULL) {
if (pData == pCurrent->pData) {
code_bits |= pCurrent->code_bits;
}
argtolower(argc, argv);
/* 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;
pCurrent = pCurrent->pNext;
}
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;
return code_bits;
}
/*--------------------------------------------------------------------------*/
static int HasLineFeed(char *pText)
{
@ -203,28 +262,67 @@ static int HasLineFeed(char *pText)
}
/*---------------------------------------------------------------------------*/
#define MAXLOG 10000
#define MAXFILES 20
static const char* timestamp(struct timeval *tp, char delim) {
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 int iFile = 0;
static int iLineCount = 0;
static int iLogUsable = 1;
static char filnam[1024];
static char prevfilnam[1024];
/*---------------------------------------------------------------------------*/
int OpenVerifyLogFile()
{
char pFile[256];
char filnam[512];
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");
if (!pChar) { /* Try to write to file "server" in */
strcpy(pFile, "server");
} 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");
if (!fLogFile) {
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;
char pBueffel[256];
int text_len;
#ifdef NOLOG
return;
#endif
text_len = strlen(pText);
/* do all captured */
pCurrent = pCapture;
while (pCurrent) {
if ((pCurrent->iOut == eOut) || (pCurrent->iAllFlag == 1)) {
ANETwrite(pCurrent->pCon->sockHandle, pText, strlen(pText));
ANETwrite(pCurrent->pCon->sockHandle, "\n", 1);
if ((pCurrent->code_bits & (1 << eOut))) {
pCurrent->pFunc(pText, eOut, pCurrent->pData);
}
pCurrent = pCurrent->pNext;
}
@ -273,23 +369,242 @@ void SICSLogWrite(char *pText, OutCode eOut)
return;
}
iLogUsable = OpenVerifyLogFile();
iLineCount = 0;
}
/* switch file if too many lines */
if (iLineCount >= MAXLOG) {
fclose(fLogFile);
fLogFile = NULL;
iFile++;
iLineCount = 0;
if (iFile >= MAXFILES) {
iFile = 0;
}
strcpy(prevfilnam, filnam);
FILE *prevlog = fLogFile;
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) {
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);
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
#include "Scommon.h"
void SICSLogWrite(char *ptext, OutCode eOut);
void SICSLogEnable(int flag);
int KillCapture(SConnection * pCon);
int LogCapture(SConnection * pCon, SicsInterp * pInter, void *pData,
int argc, char *argv[]);
void SICSLogWriteTime(char *ptext, OutCode eOut, struct timeval *tp);
void SICSLogWriteCode(char *ptext, OutCode eOut, char code);
void SICSLogWriteTimeCode(char *ptext, OutCode eOut, struct timeval *tp, char code);
void SICSLogWriteHex(const char *text, int count, OutCode eOut);
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

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;
} HdbCBInfo;
static Protocol isJSON(SConnection * pCon)
static Protocol isJSON(SConnection * pCon, int notify)
{
char proName[128];
void *pData;
if (SCinMacro(pCon)) {
if (notify == 0 && SCinMacro(pCon)) {
return normal_protocol;
}
pData = FindCommandData(pServ->pSics, "protocol", "Protocol");
@ -659,7 +659,7 @@ static hdbCallbackReturn SICSNotifyCallback(pHdb node, void *userData,
GetHdbPath(node,updatePath,sizeof(updatePath));
result = CreateDynString(128, 128);
if ((protocol = isJSON(cbInfo->pCon)) == 1)
if ((protocol = isJSON(cbInfo->pCon, 1)) == 1)
outCode = eHdbEvent;
else
outCode = eEvent;
@ -688,8 +688,11 @@ static hdbCallbackReturn SICSNotifyCallback(pHdb node, void *userData,
}
formatNameValue(protocol, updatePath, GetCharArray(printedData), result,
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);
#endif
DeleteDynString(printedData);
} else {
formatNameValue(protocol, updatePath, "!!datachange!!", result, HIPTEXT);
@ -786,7 +789,7 @@ static hdbCallbackReturn TreeChangeCallback(pHdb node, void *userData,
return hdbAbort;
}
path = GetHipadabaPath(node);
if ((protocol = isJSON(cbInfo->pCon)) == 1)
if ((protocol = isJSON(cbInfo->pCon, 1)) == 1)
outCode = eHdbEvent;
else
outCode = eEvent;
@ -1540,7 +1543,7 @@ pHdb FindHdbParent(char *rootpath, char *relpath, char **namePtr,
} else {
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);
return NULL;
}
@ -1652,7 +1655,7 @@ int GetHdbPath(pHdb nodeArg, char *path, size_t pathlen)
len = 0;
for (node = nodeArg; node != NULL && node != root; node = node->mama) {
len += strlen(node->name) + 1;
if (len >= pathlen)
if (len >= (int) pathlen)
return 0; /* buffer overflow (recursive path?) */
parent = node;
}
@ -1669,7 +1672,7 @@ int GetHdbPath(pHdb nodeArg, char *path, size_t pathlen)
}
l = strlen(sics);
len += l;
if (len > pathlen)
if (len > (int) pathlen)
return 0; /* buffer overflow */
strncpy(path, sics, l);
}
@ -2336,6 +2339,71 @@ static int MakeHdbNode(SConnection * pCon, SicsInterp * pSics, void *pData,
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)
{
@ -2559,7 +2627,7 @@ static int ZipGetHdbNode(SConnection * pCon, SicsInterp * pSics,
SCWrite(pCon, "ERROR: out of memory formatting data", eError);
return 0;
}
if ((protocol = isJSON(pCon)) == 1)
if ((protocol = isJSON(pCon, 0)) == 1)
outCode = eHdbEvent;
else
outCode = eValue;
@ -2604,7 +2672,7 @@ static int ZipReadHdbNode(SConnection * pCon, SicsInterp * pSics,
SCWrite(pCon, "ERROR: out of memory formatting data", eError);
return 0;
}
if ((protocol = isJSON(pCon)) == 1)
if ((protocol = isJSON(pCon,0)) == 1)
outCode = eHdbEvent;
else
outCode = eValue;
@ -2715,13 +2783,17 @@ static int GetHdbNode(SConnection * pCon, SicsInterp * pSics, void *pData,
}
}
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);
if (parData == NULL) {
SCWrite(pCon, "ERROR: out of memory formatting data", eError);
return 0;
}
if ((protocol = isJSON(pCon)) == 1)
if ((protocol = isJSON(pCon, 0)) == 1)
outCode = eHdbEvent;
else
outCode = eValue;
@ -2759,13 +2831,14 @@ static int GetHdbVal(SConnection * pCon, SicsInterp * pSics, void *pData,
return 0;
}
memset(&newValue, 0, sizeof(hdbValue));
GetHipadabaPar(targetNode, &newValue, pCon);
if (0 == GetHipadabaPar(targetNode, &newValue, pCon))
return 0;
parData = formatValue(newValue, targetNode);
if (parData == NULL) {
SCWrite(pCon, "ERROR: out of memory formatting data", eError);
return 0;
} else {
if ((protocol = isJSON(pCon)) == 1)
if ((protocol = isJSON(pCon, 0)) == 1)
outCode = eHdbEvent;
else
outCode = eValue;
@ -3071,7 +3144,7 @@ static int ListHdbNode(SConnection * pCon, SicsInterp * pSics, void *pData,
} else if (strcmp(argv[1], "-cli") == 0) {
listData = formatClientList(node);
} else {
if ((protocol = isJSON(pCon)) == 1) {
if ((protocol = isJSON(pCon, 0)) == 1) {
listData = formatJSONList(node);
outCode = eHdbEvent;
} else {
@ -3151,6 +3224,62 @@ static int RemoveHdbCallback(SConnection * pCon, SicsInterp * pSics,
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)
{
@ -3599,9 +3728,9 @@ static hdbCallbackReturn CommandSetCallback(pHdb node, void *userData,
}
current = current->next;
}
SendHdbStatusMessage(node, "start");
// SendHdbStatusMessage(node,"start");
status = HDBInvoke(pCon, pServ->pSics, GetCharArray(cmd));
SendHdbStatusMessage(node, "stop");
// SendHdbStatusMessage(node,"stop");
DeleteDynString(cmd);
if (status == 1) {
return hdbContinue;
@ -3632,6 +3761,60 @@ static hdbCallbackReturn CommandGetCallback(pHdb node, void *userData,
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 ================================*/
static int SetSICSHdbProperty(SConnection * pCon, SicsInterp * pSics,
void *pData, int argc, char *argv[])
@ -3681,6 +3864,30 @@ static int DelSICSHdbProperty(SConnection * pCon, SicsInterp * pSics,
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,
void *pData, int argc, char *argv[])
@ -3741,10 +3948,18 @@ static int ListSICSHdbProperty(SConnection * pCon, SicsInterp * pSics,
char buffer[512];
const char *pKey = NULL;
pDynString data = NULL;
int genTclList = 0;
if (argc < 2) {
SCWrite(pCon, "ERROR: need path as parameter", eError);
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);
if (targetNode == NULL) {
@ -3759,10 +3974,25 @@ static int ListSICSHdbProperty(SConnection * pCon, SicsInterp * pSics,
InitHdbPropertySearch(targetNode);
while ((pKey = GetNextHdbProperty(targetNode, buffer, 511)) != NULL) {
DynStringConcat(data, (char *) pKey);
if (genTclList) {
char *bp;
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);
DeleteDynString(data);
return 1;
@ -3789,24 +4019,94 @@ static int CallNotify(SConnection * pCon, SicsInterp * pSics,
return 1;
}
/*---------------------------------------------------------------------------*/
static pHdb matchHdbProp(pHdb root, char *propname, char *buffer)
static int ANSTO_ListSICSHdbProperty(SConnection * pCon,
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;
memset(value, 0, 1024);
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) {
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;
while (current != NULL) {
search = matchHdbProp(current, propname, buffer);
if (search != NULL) {
return search;
}
search =
matchHdbProp(current, propname, buffer, result, invertmatch);
current = current->next;
}
@ -3819,6 +4119,8 @@ static int MatchHdbProperty(SConnection * pCon, SicsInterp * pSics,
pHdb root = NULL;
pHdb foundNode = NULL;
char buffer[1024], *path = NULL;
int node = 1, prop = 2, propval = 3, invertmatch = 0;
pDynString matchList = NULL;
if (argc < 4) {
SCWrite(pCon,
@ -3826,25 +4128,29 @@ static int MatchHdbProperty(SConnection * pCon, SicsInterp * pSics,
eError);
return 0;
}
if (argc >= 5) {
if (strcasecmp(argv[1], "invert") == 0) {
invertmatch = 1;
node++;
prop++;
propval++;
}
}
memset(buffer, 0, 1024);
Arg2Text(argc - 3, &argv[3], buffer, 1023);
root = GetHipadabaNode(GetHipadabaRoot(), argv[1]);
Arg2Text(argc - propval, &argv[propval], buffer, 1023);
root = GetHipadabaNode(GetHipadabaRoot(), argv[node]);
if (root == NULL) {
SCWrite(pCon, "ERROR: start node for search not found", eError);
return 0;
}
strtolower(argv[2]);
strtolower(argv[prop]);
strtolower(buffer);
foundNode = matchHdbProp(root, argv[2], buffer);
if (foundNode == NULL) {
SCWrite(pCon, "NONE", eValue);
} else {
path = GetHipadabaPath(foundNode);
SCWrite(pCon, path, eValue);
free(path);
}
matchList = CreateDynString(128, 128);
foundNode =
matchHdbProp(root, argv[prop], buffer, matchList, invertmatch);
SCWrite(pCon, GetCharArray(matchList), eValue);
DeleteDynString(matchList);
return 1;
}
/*---------------------------------------------------------------------------*/
@ -3953,7 +4259,9 @@ int InstallSICSHipadaba(SConnection * pCon, SicsInterp * pSics,
{
root = MakeHipadabaNode("/", HIPNONE, 0);
AddCommand(pSics, "hmake", MakeHdbNode, NULL, NULL);
AddCommand(pSics, "hfactory", HdbNodeFactory, NULL, NULL);
AddCommand(pSics, "hmakescript", MakeHdbScriptNode, NULL, NULL);
AddCommand(pSics, "hattach", SICSHdbAdapter, NULL, NULL);
AddCommand(pSics, "hsubsamplehm", HdbSubSample, NULL, NULL);
AddCommand(pSics, "hdel", DeleteHdbNode, NULL, NULL);
@ -3967,16 +4275,20 @@ int InstallSICSHipadaba(SConnection * pCon, SicsInterp * pSics,
AddCommand(pSics, "hlist", ListHdbNode, NULL, NULL);
AddCommand(pSics, "hnotify", AutoNotifyHdbNode, NULL, NULL);
AddCommand(pSics, "hdelcb", RemoveHdbCallback, NULL, NULL);
AddCommand(pSics, "hlink", LinkHdbNode, NULL, NULL);
AddCommand(pSics, "hinfo", HdbNodeInfo, NULL, NULL);
/* AddCommand(pSics, "hval", HdbNodeVal, NULL, NULL);*/
AddCommand(pSics, "hchain", ChainHdbNode, NULL, NULL);
AddCommand(pSics, "hcommand", SicsCommandNode, NULL, NULL);
AddCommand(pSics, "harray", HdbArrayNode, NULL, NULL);
AddCommand(pSics, "hsetprop", SetSICSHdbProperty, NULL, NULL);
AddCommand(pSics, "hdelprop", DelSICSHdbProperty, NULL, NULL);
AddCommand(pSics, "hgetprop", GetSICSHdbProperty, NULL, NULL);
AddCommand(pSics, "hgetpropval", GetSICSHdbPropertyVal, NULL, NULL);
AddCommand(pSics, "hmatchprop", MatchHdbProperty, NULL, NULL);
AddCommand(pSics, "hpropexists", HasSICSHdbProperty, NULL, NULL);
AddCommand(pSics, "hlistprop", ListSICSHdbProperty, NULL, NULL);
AddCommand(pSics, "hfindprop", ANSTO_ListSICSHdbProperty, NULL, NULL);
AddCommand(pSics, "hcallnotify",CallNotify, NULL, NULL);
AddCommand(pSics, "haddcheck",AddCheck, 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
* 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
*/

View File

@ -245,7 +245,7 @@ int VarSetFloat(pSicsVariable self, float fNew, int iUserRights)
if (self->iAccessCode < iUserRights) {
return 0;
} else {
} else if (self->fVal != fNew) {
self->fVal = fNew;
InvokeCallBack(self->pCall, VALUECHANGE, self);
tracePar(self->name,"%f",fNew);
@ -261,7 +261,7 @@ int VarSetInt(pSicsVariable self, int iNew, int iUserRights)
if (self->iAccessCode < iUserRights) {
return 0;
} else {
} else if (self->iVal != iNew) {
self->iVal = iNew;
InvokeCallBack(self->pCall, VALUECHANGE, self);
tracePar(self->name,"%d",iNew);
@ -277,7 +277,7 @@ int VarSetText(pSicsVariable self, char *pNew, int iUserRights)
if (self->iAccessCode < iUserRights) {
return 0;
} else {
} else if (self->text && strcmp(self->text, pNew)) {
if (self->text) {
free(self->text);
}
@ -461,7 +461,7 @@ int VarWrapper(SConnection * pCon, SicsInterp * pInterp, void *pData,
return 1;
case veFloat:
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);
DeleteTokenList(pList);
return 1;

View File

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

View File

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

View File

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

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);
}

4
stack_trace.h Normal file
View File

@ -0,0 +1,4 @@
#ifndef STACK_TRACE_H
#define STACK_TRACE_H
void stack_trace(int mode);
#endif

View File

@ -3,7 +3,7 @@
* from the device executor and from scan and batch commands. Clients can
* listen to this in order to figure out what is actually going on in a
* given SICS installation. This might in the end supersede the status code
* managment in status.c
* management in status.c
*
* copyright: see file COPYRIGHT
*
@ -106,6 +106,7 @@ static int StateInterest(int iEvent, void *pEvent, void *pUser)
return -1;
}
if (pCon == NULL || device == NULL) {
printf("Bad StateInterest in statemon\n");
return 0;
@ -283,7 +284,7 @@ int StateMonFactory(SConnection * pCon, SicsInterp * pSics, void *pData,
if (argc > 1) {
pPtr = FindCommandData(pSics, argv[1], "ScanObject");
if (pPtr == NULL) {
SCWrite(pCon, "ERROR: failked to locate scan object", eError);
SCWrite(pCon, "ERROR: failed to locate scan object", eError);
} else {
target = GetCallbackInterface(pPtr);
assert(target != NULL);
@ -296,6 +297,20 @@ int StateMonFactory(SConnection * pCon, SicsInterp * pSics, void *pData,
return 1;
}
/*
* Context test function for callback removal
*/
int CheckConMatch(const void* context, const void* pUserData)
{
SConnection *pKon = (SConnection*) pUserData;
SConnection *pCon = (SConnection*) context;
if (VerifyConnection(pCon) && VerifyConnection(pKon)) {
if (pCon->ident == pKon->ident)
return 0;
}
return 1;
}
/*---------------------------------------------------------------------------*/
int StateMonAction(SConnection * pCon, SicsInterp * pSics, void *pData,
int argc, char *argv[])
@ -314,6 +329,7 @@ int StateMonAction(SConnection * pCon, SicsInterp * pSics, void *pData,
}
strtolower(argv[1]);
if (strcmp(argv[1], "interest") == 0) {
RemoveCallbackUsr(self->pCall, StateInterest, CheckConMatch, pCon); /* only this one */
callCon = SCCopyConnection(pCon);
if (callCon == NULL) {
SCWrite(pCon, "ERROR: out of memory registering interest", eError);
@ -324,19 +340,18 @@ int StateMonAction(SConnection * pCon, SicsInterp * pSics, void *pData,
SCRegister(pCon, pSics, self->pCall, lID);
lID = RegisterCallback(self->pCall, STEND, StateInterest,
callCon, NULL);
SCRegister(pCon, pSics, self->pCall, lID);
SCSendOK(pCon);
return 1;
} else if (strcmp(argv[1], "uninterest") == 0) {
for (i = 0; i < 2; i++) {
lID = SCgetCallbackID(pCon, self->pCall);
if (lID >= 0) {
RemoveCallback(self->pCall, lID);
}
}
RemoveCallbackUsr(self->pCall, StateInterest, CheckConMatch, pCon); /* only this one */
SCSendOK(pCon);
return 1;
} else if (strcmp(argv[1], "hdbuninterest") == 0) {
RemoveCallbackUsr(self->pCall, StateHdbInterest, CheckConMatch, pCon); /* only this one */
SCSendOK(pCon);
return 1;
} else if (strcmp(argv[1], "hdbinterest") == 0) {
RemoveCallbackUsr(self->pCall, StateHdbInterest, CheckConMatch, pCon); /* only this one */
callCon = SCCopyConnection(pCon);
if (callCon == NULL) {
SCWrite(pCon, "ERROR: out of memory registering interest", eError);

View File

@ -58,7 +58,7 @@ int StatisticsCommand(SConnection * con, SicsInterp * pSics, void *pData,
gettimeofday(&now, 0);
dif = timeFloat(timeDif(lastStat, now));
SCPrintf(con, eLog, "calls/s time[%] full[%] mean[ms] command");
SCPrintf(con, eLog, "calls/s time[%%] full[%%] mean[ms] command");
SCPrintf(con, eLog, "----------------------------------------------");
for (p = list; p != NULL; p = p->next) {
if (dif > 0) {

View File

@ -52,12 +52,17 @@
#include "lld.h"
#include "exebuf.h"
#define CLEAN_LOCKED 1
#define CLEAN_MISSING 2
static int parameterChange = 0;
/*-----------------------------------------------------------------------*/
int StatusFileTask(void *data)
{
char *pFile = NULL;
if (!hasRestored())
return 1;
if (parameterChange) {
parameterChange = 0;
@ -215,6 +220,94 @@ static int listRestoreErr(pRestoreObj self, SConnection * pCon)
return 1;
}
/*-----------------------------------------------------------------------*/
static int cleanRestoreErr(pRestoreObj self, SConnection * pCon, int hard)
{
char command[1024];
char message[1024];
char *errMsg = NULL;
int status;
int newErrList;
pDynString data = NULL;
pStringDict dict;
int count_in = 0;
int count_ex = 0;
if (!self->errList)
return 1;
data = CreateDynString(256,256);
if (data == NULL) {
SCWrite(pCon,"ERROR: out of memory cleaning errors",eError);
return 0;
}
dict = CreateStringDict();
if (dict == NULL) {
SCWrite(pCon,"ERROR: out of memory cleaning errors",eError);
DeleteDynString(data);
return 0;
}
/* create new list */
newErrList = LLDstringCreate();
if (newErrList < 0) {
SCWrite(pCon,"ERROR: out of blobs cleaning errors",eError);
DeleteDynString(data);
DeleteStringDict(dict);
return 0;
}
status = LLDnodePtr2First(self->errList);
while (status == 1) {
LLDstringData(self->errList, command);
status = LLDnodePtr2Next(self->errList);
if (status != 1) {
/* Error */
errMsg = "ERROR: unpaired error cleaning errors";
break;
}
LLDstringData(self->errList, message);
if (command[0] == '#' || message[0] != '#') {
/* Error */
errMsg = "ERROR: sequence error cleaning errors";
break;
}
DynStringClear(data);
DynStringConcat(data, command);
DynStringConcat(data, message);
status = LLDnodePtr2Next(self->errList);
++count_in;
/* Skip duplicate messages */
if (StringDictExists(dict, GetCharArray(data)))
continue;
/* Skip "configured locked!" messages */
if (hard == CLEAN_LOCKED &&
strstr(message, "#ERR: ERROR: variable ") &&
strstr(message, " is configured locked!"))
continue;
/* Skip "not found" messages */
if (hard == CLEAN_MISSING &&
strstr(message, "#ERR: Object ") &&
strstr(message, "not found"))
continue;
/* add to dictionary and new list */
StringDictAddPair(dict, GetCharArray(data), "");
LLDstringAppend(newErrList, command);
LLDstringAppend(newErrList, message);
++count_ex;
}
if (errMsg) {
SCWrite(pCon, errMsg, eError);
LLDstringDelete(newErrList);
} else {
/* swap lists */
LLDstringDelete(self->errList);
self->errList = newErrList;
SCPrintf(pCon, eLog, "CleanErr: %d pairs in, %d pairs out", count_in, count_ex);
}
DeleteDynString(data);
DeleteStringDict(dict);
return 1;
}
/*-----------------------------------------------------------------------*/
int RestoreStatus(SConnection * pCon, SicsInterp * pSics, void *pData,
int argc, char *argv[])
@ -243,6 +336,13 @@ int RestoreStatus(SConnection * pCon, SicsInterp * pSics, void *pData,
} else {
if (strcasecmp(argv[1], "listerr") == 0) {
return listRestoreErr(self, pCon);
} else if (strcasecmp(argv[1], "cleanerr") == 0) {
if (argc > 2 && strcasecmp(argv[2], "locked") == 0)
return cleanRestoreErr(self, pCon, CLEAN_LOCKED);
else if (argc > 2 && strcasecmp(argv[2], "missing") == 0)
return cleanRestoreErr(self, pCon, CLEAN_MISSING);
else
return cleanRestoreErr(self, pCon, 0);
} else if (strcasecmp(argv[1], "killerr") == 0) {
if (self->errList >= 0) {
LLDdeleteBlob(self->errList);

View File

@ -540,7 +540,7 @@ int WriteScanPoints(pScanData self, int iPoint)
strlcat(pLine, pItem,1024);
snprintf(pItem,sizeof(pItem)-1, "%-11ld ", pData->Monitors[2]);
strlcat(pLine, pItem,1024);
snprintf(pItem,sizeof(pItem)-1, "%-5.1f ", pData->fTime);
snprintf(pItem,sizeof(pItem)-1, "%-8.3f ", pData->fTime);
strlcat(pLine, pItem,1024);
}
fprintf(self->fd, "%s\n", pLine);

3
task.c
View File

@ -338,12 +338,14 @@ int TaskYield(pTaskMan self)
int TaskSignal(pTaskMan self, int iSignal, void *pSigData)
{
pTaskHead pTemp, pEnd;
int myStatus = self->pCurrent->iStatus;
assert(self);
assert(self->iID == TASKERID);
/* Do one cycle until we are at the caller, then return to him */
pEnd = self->pCurrent;
pEnd->iStatus = WAITING;
IncrTaskPointer(self);
while (self->pCurrent != pEnd) {
if (self->pCurrent->pSignal) {
@ -352,6 +354,7 @@ int TaskSignal(pTaskMan self, int iSignal, void *pSigData)
IncrTaskPointer(self);
}
/* finally, tell me about the thingie as well */
pEnd->iStatus = myStatus;
if (pEnd->pSignal) {
pEnd->pSignal(pEnd->pData, iSignal, pSigData);
}

40
tasub.c
View File

@ -257,6 +257,7 @@ int TasUBFactory(SConnection * pCon, SicsInterp * pSics, void *pData,
"ef", "kf",
"en"
};
char *defltMot[] = {"a1", "a2", "mcv", "mch", "a3", "a4", "sgu", "sgl", "a5", "a6", "acv", "ach"};
if (argc < 2) {
SCWrite(pCon, "ERROR: need name to install tasUB", eError);
@ -292,6 +293,10 @@ int TasUBFactory(SConnection * pCon, SicsInterp * pSics, void *pData,
pNew->motors[9] = TasFindMotor(pSics, "a6");
pNew->motors[10] = TasFindMotor(pSics, "acv");
pNew->motors[11] = TasFindMotor(pSics, "ach");
for (i=0; i < 12; i++) {
strcpy(pNew->motname[i], defltMot[i]);
}
} else {
/*
* user defined names
@ -308,18 +313,21 @@ int TasUBFactory(SConnection * pCon, SicsInterp * pSics, void *pData,
pNew->motors[9] = TasFindMotor(pSics, argv[11]);
pNew->motors[10] = TasFindMotor(pSics, argv[12]);
pNew->motors[11] = TasFindMotor(pSics, argv[13]);
for (i=0; i < 12; i++) {
strcpy(pNew->motname[i], argv[i+2]);
}
}
/*
curvature motors may be missing, anything else is a serious problem
*/
status += testMotor(pNew, pCon, "a1", A1);
status += testMotor(pNew, pCon, "a2", A2);
status += testMotor(pNew, pCon, "a3", A3);
status += testMotor(pNew, pCon, "a4", A4);
status += testMotor(pNew, pCon, "sgu", SGU);
status += testMotor(pNew, pCon, "sgl", SGL);
status += testMotor(pNew, pCon, "a5", A5);
status += testMotor(pNew, pCon, "a6", A6);
status += testMotor(pNew, pCon, pNew->motname[A1], A1);
status += testMotor(pNew, pCon, pNew->motname[A2], A2);
status += testMotor(pNew, pCon, pNew->motname[A3], A3);
status += testMotor(pNew, pCon, pNew->motname[A4], A4);
status += testMotor(pNew, pCon, pNew->motname[SGU], SGU);
status += testMotor(pNew, pCon, pNew->motname[SGL], SGL);
status += testMotor(pNew, pCon, pNew->motname[A5], A5);
status += testMotor(pNew, pCon, pNew->motname[A6], A6);
if (status != 8) {
SCWrite(pCon, "ERROR: a required motor is missing, tasub NOT installed",
eError);
@ -582,7 +590,9 @@ static void listReflections(ptasUB self, SConnection * pCon)
Tcl_DStringInit(&list);
snprintf(line, 255,
" NO QH QK QL A3 A4 SGU SGL EI EF\n");
" NO QH QK QL %s %s %s %s EI EF\n",
self->motname[A3], self->motname[A4], self->motname[SGU],
self->motname[SGL]);
Tcl_DStringAppend(&list, line, -1);
status = LLDnodePtr2First(self->reflectionList);
while (status == 1) {
@ -726,7 +736,9 @@ static int addReflection(ptasUB self, SicsInterp * pSics,
LLDnodeAppend(self->reflectionList, &r);
Tcl_DStringInit(&list);
snprintf(pBueffel, 255,
" QH QK QL A3 A4 SGU SGL EI EF\n");
" QH QK QL %s %s %s %s EI EF\n",
self->motname[A3], self->motname[A4], self->motname[SGU],
self->motname[SGL]);
Tcl_DStringAppend(&list, pBueffel, -1);
snprintf(pBueffel, 255,
" %6.2f %6.2f %6.2f %7.2f %7.2f %6.2f %6.2f %6.2f %6.2f\n",
@ -880,7 +892,9 @@ static void listUB(ptasUB self, SConnection * pCon)
snprintf(pBueffel, 255, "UB generated from reflections:\n");
Tcl_DStringAppend(&list, pBueffel, -1);
snprintf(pBueffel, 255,
" QH QK QL A3 A4 SGU SGL EI EF\n");
" QH QK QL %s %s %s %s EI EF\n",
self->motname[A3], self->motname[A4], self->motname[SGU],
self->motname[SGL]);
Tcl_DStringAppend(&list, pBueffel, -1);
r = self->r1;
snprintf(pBueffel, 255,
@ -920,7 +934,9 @@ static void printReflectionDiagnostik(ptasUB self, SConnection * pCon,
Tcl_DStringInit(&list);
snprintf(line, 255,
"METHOD QH QK QL A3 A4 SGU SGL EI EF\n");
"METHOD QH QK QL %s %s %s %s EI EF\n",
self->motname[A3], self->motname[A4], self->motname[SGU],
self->motname[SGL]);
Tcl_DStringAppend(&list, line, -1);
snprintf(line, 255,
"INPUT %8.4f %8.4f %8.4f %7.2f %7.2f %6.2f %6.2f %6.2f %6.2f\n",

View File

@ -29,6 +29,7 @@
int mustDrive;
int mustDriveQ;
pMotor motors[12];
char motname[12][32];
tasReflection r1, r2;
pIDrivable mono;
long monoTaskID;

View File

@ -1,5 +1,5 @@
#
# $Id: object.tcl,v 1.1 2006/10/20 14:57:27 koennecke Exp $
# $Id$
#
# This software is copyright (C) 1995 by the Lawrence Berkeley Laboratory.
#

View File

@ -16,7 +16,7 @@
# Contributions from Don Porter, NIST, 2002. (not subject to US copyright)
# All rights reserved.
#
# RCS: @(#) $Id: tcltest.tcl,v 1.1 2006/08/16 14:17:42 koennecke Exp $
# RCS: @(#) $Id$
package require Tcl 8.3 ;# uses [glob -directory]
namespace eval tcltest {

19
trace.h
View File

@ -18,17 +18,24 @@
* the socket number, a host:port or something appropriate
* which tells us where the stuff is going to or coming from.
*/
void traceIO(char *id, char *format, ...);
void traceDevice(char *id, char *format, ...);
void traceCommand(char *id, char *format, ...);
void tracePar(char *id, char *format, ...);
void traceSys(char *id, char *format, ...);
#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 traceIO(char *id, char *format, ...) G_GNUC_PRINTF (2, 3);
void traceDevice(char *id, char *format, ...) G_GNUC_PRINTF (2, 3);
void traceCommand(char *id, char *format, ...) G_GNUC_PRINTF (2, 3);
void tracePar(char *id, char *format, ...) G_GNUC_PRINTF (2, 3);
void traceSys(char *id, char *format, ...) G_GNUC_PRINTF (2, 3);
void traceprint(char *sub, char *id,char *data);
/**
* A debugging trace. This has to be switched on separately
*/
void traceDebug(char *id, char *format, ...);
void traceDebug(char *id, char *format, ...) G_GNUC_PRINTF (2, 3);
#undef G_GNUC_PRINTF
/*
* 1 when tracing active, 0 else