Merge branch 'develop' into moreremo
This commit is contained in:
79
SICSmain.c
79
SICSmain.c
@ -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) {
|
||||
SICSLogEnable(0);
|
||||
}else if(strcmp(argv[i],"-keepstartup") == 0){
|
||||
KeepStartupCommands();
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -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 */
|
||||
|
6
ascon.c
6
ascon.c
@ -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;
|
||||
}
|
||||
@ -812,7 +816,7 @@ char *AsconRead(Ascon * a)
|
||||
{
|
||||
if (a->noResponse) {
|
||||
a->noResponse = 0;
|
||||
return "";
|
||||
return NULL;
|
||||
}
|
||||
if (a->state != AsconIdle) {
|
||||
a->state = AsconIdle;
|
||||
|
117
asyncprotocol.c
117
asyncprotocol.c
@ -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) {
|
||||
*result++ = '0';
|
||||
*result++ = 'x';
|
||||
*result++ = hex[(*terminator >> 4) & 0xF];
|
||||
*result++ = hex[(*terminator) & 0xF];
|
||||
++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,39 +238,54 @@ int AsyncProtocolAction(SConnection * pCon, SicsInterp * pSics,
|
||||
return 1;
|
||||
} else if (strcasecmp(argv[1], "replyterminator") == 0) {
|
||||
if (argc > 2) {
|
||||
char *pPtr = decodeTerminator(argv[2]);
|
||||
if (pPtr) {
|
||||
if (self->replyTerminator)
|
||||
free(self->replyTerminator);
|
||||
self->replyTerminator = pPtr;
|
||||
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) {
|
||||
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 };
|
||||
av[1] = "sendterminator";
|
||||
AsyncProtocolAction(pCon, pSics, pData, ac, av);
|
||||
av[1] = "replyterminator";
|
||||
AsyncProtocolAction(pCon, pSics, pData, ac, av);
|
||||
return 1;
|
||||
}
|
||||
} else if (strcasecmp(argv[1], "list") == 0) {
|
||||
int ac = 2;
|
||||
char *av[3] = { argv[0], 0, 0 };
|
||||
av[1] = "sendterminator";
|
||||
AsyncProtocolAction(pCon, pSics, pData, ac, av);
|
||||
av[1] = "replyterminator";
|
||||
AsyncProtocolAction(pCon, pSics, pData, ac, av);
|
||||
return 1;
|
||||
}
|
||||
/* handle any other actions here */
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
636
asyncqueue.c
636
asyncqueue.c
@ -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
|
||||
*/
|
||||
while (NETAvailable(sock, 0)) {
|
||||
/* TODO: handle unsolicited input */
|
||||
char reply[1];
|
||||
int iRet;
|
||||
iRet = NETRead(sock, reply, 1, 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);
|
||||
if (NETAvailable(sock, 0)) {
|
||||
while (NETAvailable(sock, 0)) {
|
||||
/* TODO: handle unsolicited input */
|
||||
char reply[128];
|
||||
iRet = NETRead(sock, reply, 128, 0);
|
||||
if (iRet < 0) { /* EOF */
|
||||
iRet = AQ_Reconnect(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) {
|
||||
iRet =
|
||||
self->protocol->handleInput(self->protocol, myCmd->tran,
|
||||
reply[0]);
|
||||
if (iRet == 0 || iRet == AQU_POP_CMD) { /* end of command */
|
||||
if (myCmd->tran->handleResponse)
|
||||
myCmd->tran->handleResponse(myCmd->tran);
|
||||
PopCommand(self);
|
||||
} else if (iRet < 0) /* TODO: error */
|
||||
;
|
||||
for (i = 0; i < nchars; ++i) {
|
||||
iRet =
|
||||
self->protocol->handleInput(self->protocol, myCmd->tran,
|
||||
reply[i] & 0xFF);
|
||||
if (iRet == 0 || iRet == AQU_POP_CMD) { /* end of command */
|
||||
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);
|
||||
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;
|
||||
}
|
||||
|
29
asyncqueue.h
29
asyncqueue.h
@ -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 */
|
||||
|
10
asynnet.c
10
asynnet.c
@ -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);
|
||||
FD_SET(socke, &writeMask);
|
||||
if (connections[i].writeBuffer != NULL) {
|
||||
GetRWBufferData(connections[i].writeBuffer, &length);
|
||||
if (length > 0)
|
||||
FD_SET(socke, &writeMask);
|
||||
else
|
||||
connections[i].lastOpenForWrite = time(NULL);
|
||||
}
|
||||
if (socke > count) {
|
||||
count = socke;
|
||||
}
|
||||
|
30
callback.c
30
callback.c
@ -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)
|
||||
{
|
||||
|
@ -174,8 +174,8 @@ static void KillAdapter(void *pData)
|
||||
if (self->pInt)
|
||||
free(self->pInt);
|
||||
|
||||
if (self->pParName);
|
||||
free(self->pParName);
|
||||
if (self->pParName)
|
||||
free(self->pParName);
|
||||
|
||||
free(self);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -17,6 +17,7 @@ typedef struct __CONFVIRTMOT {
|
||||
float targetValue;
|
||||
int targetReached;
|
||||
int posCount;
|
||||
double last_report_time;
|
||||
char scriptError[512];
|
||||
int parseOK;
|
||||
}ConfigurableVirtualMotor, *pConfigurableVirtualMotor;
|
||||
|
@ -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]);
|
||||
|
@ -22,6 +22,7 @@ typedef struct __CONFVIRTMOT {
|
||||
float targetValue;
|
||||
int targetReached;
|
||||
int posCount;
|
||||
double last_report_time;
|
||||
char scriptError[512];
|
||||
int parseOK;
|
||||
}ConfigurableVirtualMotor, *pConfigurableVirtualMotor;
|
||||
|
278
conman.c
278
conman.c
@ -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)
|
||||
{
|
||||
@ -652,7 +678,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);
|
||||
@ -781,6 +807,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)
|
||||
{
|
||||
@ -795,7 +879,11 @@ int SCNormalWrite(SConnection * self, char *buffer, int iOut)
|
||||
}
|
||||
|
||||
/* log it for any case */
|
||||
SICSLogWrite(buffer, iOut);
|
||||
#if 0
|
||||
SICSLogWrite(buffer, iOut);
|
||||
#else
|
||||
testAndWriteSICSLog(self, buffer, iOut);
|
||||
#endif
|
||||
|
||||
testAndWriteCommandLog(self, buffer, iOut);
|
||||
|
||||
@ -2144,6 +2232,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)
|
||||
{
|
||||
@ -2214,7 +2486,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';
|
||||
|
9
conman.h
9
conman.h
@ -93,7 +93,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
16
costa.c
@ -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;
|
||||
}
|
||||
|
||||
|
1
costa.h
1
costa.h
@ -25,5 +25,6 @@ int CostaPop(pCosta self, char **pPtr);
|
||||
/*----------------------------------------------------------------------*/
|
||||
void CostaLock(pCosta self);
|
||||
void CostaUnlock(pCosta self);
|
||||
int CostaLocked(pCosta self);
|
||||
|
||||
#endif
|
||||
|
@ -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;
|
||||
|
@ -42,6 +42,7 @@ typedef struct __COUNTER {
|
||||
float fLastCurrent;
|
||||
float fTime;
|
||||
int iNoOfMonitors;
|
||||
int iControlMonitor;
|
||||
long lCounts[MAXCOUNT];
|
||||
int iPause;
|
||||
int iErrorCode;
|
||||
|
64
counter.c
64
counter.c
@ -551,7 +551,7 @@ static int SetCounterModeImpl(pCounter self, CounterMode eNew)
|
||||
/*-------------------------------------------------------------------------*/
|
||||
CounterMode GetCounterMode(pCounter self)
|
||||
{
|
||||
return self->getMode(self);
|
||||
return self->getMode(self);
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
static CounterMode GetCounterModeImpl(pCounter self)
|
||||
@ -562,7 +562,7 @@ static CounterMode GetCounterModeImpl(pCounter self)
|
||||
/*------------------------------------------------------------------------*/
|
||||
int GetNMonitor(pCounter self)
|
||||
{
|
||||
return self->getNMonitor(self);
|
||||
return self->getNMonitor(self);
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
static int GetNMonitorImpl(pCounter self)
|
||||
@ -571,13 +571,28 @@ 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
|
||||
/*------------------------------------------------------------------------*/
|
||||
int SetCounterPreset(pCounter self, float fVal)
|
||||
{
|
||||
return self->setPreset(self,fVal);
|
||||
return self->setPreset(self,fVal);
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
static int SetCounterPresetImpl(pCounter self, float fVal)
|
||||
@ -603,17 +618,17 @@ static int SetCounterPresetImpl(pCounter self, float fVal)
|
||||
/*------------------------------------------------------------------------*/
|
||||
float GetCounterPreset(pCounter self)
|
||||
{
|
||||
return self->getPreset(self);
|
||||
return self->getPreset(self);
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
float GetControlValue(pCounter self)
|
||||
{
|
||||
return self->getControlValue(self);
|
||||
return self->getControlValue(self);
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
static float GetControlValueImpl(pCounter self)
|
||||
{
|
||||
return self->pDriv->fLastCurrent;
|
||||
return self->pDriv->fLastCurrent;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
static float GetCounterPresetImpl(pCounter self)
|
||||
@ -634,7 +649,7 @@ static float GetCounterPresetImpl(pCounter self)
|
||||
/*-----------------------------------------------------------------------*/
|
||||
long GetCounts(pCounter self, SConnection * pCon)
|
||||
{
|
||||
return self->getCounts(self, pCon);
|
||||
return self->getCounts(self, pCon);
|
||||
}
|
||||
/*-----------------------------------------------------------------------*/
|
||||
static long GetCountsImpl(pCounter self, SConnection * pCon)
|
||||
@ -643,12 +658,12 @@ 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)
|
||||
{
|
||||
return self->getMonitor(self, iNum, pCon);
|
||||
return self->getMonitor(self, iNum, pCon);
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
static long GetMonitorImpl(pCounter self, int iNum, SConnection * pCon)
|
||||
@ -658,7 +673,7 @@ static long GetMonitorImpl(pCounter self, int iNum, SConnection * pCon)
|
||||
if (!self->isUpToDate) {
|
||||
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];
|
||||
@ -667,7 +682,7 @@ static long GetMonitorImpl(pCounter self, int iNum, SConnection * pCon)
|
||||
/*-----------------------------------------------------------------------*/
|
||||
void SetMonitorValue(pCounter self, int index, long value)
|
||||
{
|
||||
return self->setMonitor(self, index, value);
|
||||
return self->setMonitor(self, index, value);
|
||||
}
|
||||
/*-----------------------------------------------------------------------*/
|
||||
static void SetMonitorValueImpl(pCounter self, int index, long value)
|
||||
@ -681,7 +696,7 @@ static void SetMonitorValueImpl(pCounter self, int index, long value)
|
||||
/*------------------------------------------------------------------------*/
|
||||
float GetCountTime(pCounter self, SConnection * pCon)
|
||||
{
|
||||
return self->getTime(self, pCon);
|
||||
return self->getTime(self, pCon);
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
static float GetCountTimeImpl(pCounter self, SConnection * pCon)
|
||||
@ -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,8 +866,8 @@ int CountAction(SConnection * pCon, SicsInterp * pSics, void *pData,
|
||||
argtolower(argc, argv);
|
||||
argx = &argv[1];
|
||||
iRet =
|
||||
EvaluateFuPa((pFuncTemplate) & ActionTemplate, 26, argc - 1, argx,
|
||||
&PaRes);
|
||||
EvaluateFuPa((pFuncTemplate) & ActionTemplate, 28, argc - 1, argx,
|
||||
&PaRes);
|
||||
if (iRet < 0) {
|
||||
snprintf(pBueffel, 255,"%s", PaRes.pError);
|
||||
SCWrite(pCon, pBueffel, eError);
|
||||
@ -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 */
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
21
countersec.c
21
countersec.c
@ -177,10 +177,23 @@ static int SecCtrCheckStatus(void *pData, SConnection *pCon)
|
||||
ReleaseHdbValue(&v);
|
||||
|
||||
|
||||
node = GetHipadabaNode(self->pDes->parNode,"control");
|
||||
assert(node != NULL);
|
||||
GetHipadabaPar(node,&v,pCon);
|
||||
fControl = v.v.doubleValue;
|
||||
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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
3
devser.c
3
devser.c
@ -151,9 +151,6 @@ static DevAction *DevNextAction(DevSer * devser)
|
||||
}
|
||||
static void LogStart(DevSer *self)
|
||||
{
|
||||
if(self->startTime > 0){
|
||||
printf("DEVSER: there is something fucked up in LogStart. Investigate!\n");
|
||||
}
|
||||
self->startTime = DoubleTime();
|
||||
}
|
||||
static void LogResponse(DevSer *self, int error)
|
||||
|
117
diffscan.c
117
diffscan.c
@ -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
|
||||
@ -303,7 +376,7 @@ static int DiffScanTask(void *pData)
|
||||
status = GetDrivablePosition(pVar->pObject, self->scanObject->pCon,
|
||||
&fPos);
|
||||
if (status == 0) {
|
||||
ReleaseCountLock(pCount->pCountInt);
|
||||
ReleaseCountLock(pCount->pCountInt);
|
||||
return finish;
|
||||
}
|
||||
AppendScanVar(pVar, fPos);
|
||||
@ -323,21 +396,21 @@ static int DiffScanTask(void *pData)
|
||||
rawCount = data->lCount;
|
||||
rawMon = data->Monitors[self->scaleMonitor - 1];
|
||||
if(rawMon > 100){
|
||||
self->normalizationScale = rawMon;
|
||||
traceSys("diffscan","START:normalizing on %d, scale monitor is %d",
|
||||
self->normalizationScale, self->scaleMonitor);
|
||||
self->normalizationScale = rawMon;
|
||||
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",
|
||||
rawMon, self->scaleMonitor);
|
||||
SCWrite(self->scanObject->pCon,"WARNING: Skipping first point because of low count rate", eWarning);
|
||||
return finish;
|
||||
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;
|
||||
}
|
||||
} else {
|
||||
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],
|
||||
self->last.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;
|
||||
rawMon = data->Monitors[self->scaleMonitor - 1];
|
||||
@ -350,13 +423,26 @@ 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",
|
||||
fPos, countValue, rawCount, rawMon);
|
||||
traceSys("diffscan","RUN: pos, count, rawcount, rawmon: %f, %f, %ld, %ld",
|
||||
fPos, countValue, rawCount, rawMon);
|
||||
|
||||
/*
|
||||
check for interrupt
|
||||
@ -369,7 +455,7 @@ static int DiffScanTask(void *pData)
|
||||
}
|
||||
|
||||
if(finish == 0) {
|
||||
ReleaseCountLock(pCount->pCountInt);
|
||||
ReleaseCountLock(pCount->pCountInt);
|
||||
}
|
||||
|
||||
return finish;
|
||||
@ -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);
|
||||
|
||||
|
||||
|
@ -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;
|
||||
|
||||
/*==================================================================*/
|
||||
|
@ -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.
@ -1 +0,0 @@
|
||||
\relax
|
@ -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}
|
||||
|
@ -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
12
drive.c
@ -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);
|
||||
|
@ -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
|
||||
|
5
exebuf.c
5
exebuf.c
@ -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++;
|
||||
|
16
hipadaba.c
16
hipadaba.c
@ -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)
|
||||
{
|
||||
|
@ -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
|
||||
|
1
ifile.c
1
ifile.c
@ -47,6 +47,7 @@
|
||||
#include "ifile.h"
|
||||
|
||||
/*====================== Locals ============================================*/
|
||||
IPair *pSICSOptions = NULL;
|
||||
|
||||
static IPair *CreateNewEntry(char *name, char *val, IPair * pN)
|
||||
{
|
||||
|
@ -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
1
lld.c
@ -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 ... */
|
||||
|
3
logger.c
3
logger.c
@ -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)
|
||||
|
@ -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,
|
||||
|
5
macro.c
5
macro.c
@ -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) {
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
*
|
||||
|
@ -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!
|
||||
*
|
||||
|
3
modriv.h
3
modriv.h
@ -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 */
|
||||
|
47
motor.c
47
motor.c
@ -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;
|
||||
InvokeCallBack(self->pCall, MOTDRIVE, &sCall); /* send also very last position */
|
||||
InvokeCallBack(self->pCall, MOTEND, &sCall);
|
||||
tracePar(self->name,"%f",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;
|
||||
|
3
motor.h
3
motor.h
@ -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 *);
|
||||
|
@ -298,7 +298,7 @@ static int SecMotorStatus(void *sulf, SConnection * pCon)
|
||||
int status;
|
||||
pHdb node = NULL;
|
||||
hdbValue v;
|
||||
float interrupt;
|
||||
float interrupt = 0.;
|
||||
char error[132];
|
||||
|
||||
assert(sulf);
|
||||
|
@ -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
|
||||
|
4
napiu.c
4
napiu.c
@ -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>
|
||||
|
2
napiu.h
2
napiu.h
@ -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$
|
||||
|
||||
----------------------------------------------------------------------------*/
|
||||
|
||||
|
29
network.c
29
network.c
@ -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;
|
||||
|
38
nread.c
38
nread.c
@ -294,15 +294,25 @@ 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);
|
||||
iStat = CostaTop(pItem->pCon->pStack, pItem->pHold);
|
||||
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);
|
||||
}
|
||||
pItem->pHold[0] = '\0';
|
||||
} else {
|
||||
/* no, normal command */
|
||||
iStat = CostaTop(pItem->pCon->pStack, pPtr);
|
||||
/* 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,7 +497,12 @@ static int TelnetRead(pNetRead self, pNetItem pItem)
|
||||
break;
|
||||
case '\r':
|
||||
case '\n':
|
||||
iStat = CostaTop(pItem->pCon->pStack, pItem->pHold);
|
||||
/* 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) {
|
||||
SCWrite(pItem->pCon, "ERROR: Busy", eError);
|
||||
@ -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);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------------------*/
|
||||
|
34
nserver.c
34
nserver.c
@ -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;
|
||||
}
|
||||
|
114
nwatch.c
114
nwatch.c
@ -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 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,19 +292,19 @@ 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)
|
||||
self->cq_tail = pNxt;
|
||||
/* 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;
|
||||
|
||||
@ -375,7 +385,7 @@ int NetWatchTask(void *pData)
|
||||
if (self->nInvalid > 0)
|
||||
NetWatchContextPrgQue(self);
|
||||
|
||||
/* build the select mask */
|
||||
/* build the select mask */
|
||||
FD_ZERO(&rMask);
|
||||
FD_ZERO(&wMask);
|
||||
pNWC = self->cq_head;
|
||||
@ -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
|
||||
|
12
nwatch.h
12
nwatch.h
@ -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
126
nxdict.c
@ -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)
|
||||
|
52
nxscript.c
52
nxscript.c
@ -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;
|
||||
}
|
||||
|
||||
|
4
obpar.c
4
obpar.c
@ -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
9
ofac.c
@ -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;
|
||||
}
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
@ -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);
|
||||
|
2
sansbc.c
2
sansbc.c
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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,21 +432,22 @@ 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') {
|
||||
SCPrintf(con, eLog, "%6.3f reply : %s\n", secondsOfMinute(), lastReply);
|
||||
}
|
||||
if(!commError && controller->fd != NULL && lastReply != NULL && *lastReply != '\0'){
|
||||
fprintf(controller->fd, "%6.3f reply : %s\n", secondsOfMinute(), lastReply);
|
||||
}
|
||||
if(lastReply != NULL && *lastReply != '\0'){
|
||||
if(data != NULL && data->controller != NULL){
|
||||
traceIO(data->controller->node->name, "reply:%s", lastReply);
|
||||
} else {
|
||||
traceIO("sctunknown", "reply:%s", lastReply);
|
||||
}
|
||||
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) {
|
||||
fprintf(controller->fd, "%6.3f reply : %s\n", secondsOfMinute(), lastReply);
|
||||
}
|
||||
if(data != NULL && data->controller != NULL) {
|
||||
traceIO(data->controller->node->name, "reply:%s", lastReply);
|
||||
} else {
|
||||
traceIO("sctunknown", "reply:%s", lastReply);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -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) {
|
||||
@ -536,7 +553,7 @@ static char *SctActionHandler(void *actionData, char *lastReply,
|
||||
} else {
|
||||
l = strlen(origScript);
|
||||
}
|
||||
snprintf(eprop, sizeof eprop, "error_in_%.*s", l, origScript);
|
||||
snprintf(eprop, sizeof eprop, "error_in_%s", origScript);
|
||||
emsg = GetHdbProp(node, eprop);
|
||||
cnt = 0;
|
||||
if (emsg != 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));
|
||||
|
@ -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;
|
||||
|
517
servlog.c
517
servlog.c
@ -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;
|
||||
}
|
||||
pCurrent = pCurrent->pNext;
|
||||
}
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
26
servlog.h
26
servlog.h
@ -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
4
sicsglobal.c
Normal 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
6
sicsglobal.h
Normal file
@ -0,0 +1,6 @@
|
||||
#ifndef SICSGLOBAL_H
|
||||
#define SICSGLOBAL_H
|
||||
|
||||
extern const char *argv0;
|
||||
extern int isDuringInitialization;
|
||||
#endif
|
394
sicshipadaba.c
394
sicshipadaba.c
@ -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,9 +3974,24 @@ static int ListSICSHdbProperty(SConnection * pCon, SicsInterp * pSics,
|
||||
InitHdbPropertySearch(targetNode);
|
||||
while ((pKey = GetNextHdbProperty(targetNode, buffer, 511)) != NULL) {
|
||||
DynStringConcat(data, (char *) pKey);
|
||||
DynStringConcat(data, "=");
|
||||
DynStringConcat(data, buffer);
|
||||
DynStringConcat(data, "\n");
|
||||
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);
|
||||
@ -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 (GetHdbProperty(root, propname, value, 1023) == 1) {
|
||||
if (strcmp(buffer, "*") == 0) {
|
||||
if (GetHdbProperty(root, propname, value, 1023) == 1) {
|
||||
if (!invertmatch) {
|
||||
path = GetHipadabaPath(root);
|
||||
DynStringConcat(result, path);
|
||||
DynStringConcat(result, "\n");
|
||||
free(path);
|
||||
}
|
||||
} else if (invertmatch) {
|
||||
path = GetHipadabaPath(root);
|
||||
DynStringConcat(result, path);
|
||||
DynStringConcat(result, "\n");
|
||||
free(path);
|
||||
}
|
||||
} else if (GetHdbProperty(root, propname, value, 1023) == 1) {
|
||||
if (strstr(buffer, value) != NULL) {
|
||||
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);
|
||||
|
27
sicslist.c
27
sicslist.c
@ -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
|
||||
*/
|
||||
|
8
sicvar.c
8
sicvar.c
@ -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;
|
||||
|
@ -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;
|
||||
|
1
simidx.h
1
simidx.h
@ -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);
|
||||
|
||||
/**
|
||||
|
2
sinfox.h
2
sinfox.h
@ -56,7 +56,7 @@ char *pDeviceTypes[25] = {
|
||||
"connection",
|
||||
"crystalselector",
|
||||
"environment monitor",
|
||||
"environment controller",
|
||||
"environment_controller",
|
||||
"gpib",
|
||||
"hklscan",
|
||||
"hmcontrol",
|
||||
|
322
stack_trace.c
Normal file
322
stack_trace.c
Normal 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
4
stack_trace.h
Normal file
@ -0,0 +1,4 @@
|
||||
#ifndef STACK_TRACE_H
|
||||
#define STACK_TRACE_H
|
||||
void stack_trace(int mode);
|
||||
#endif
|
35
statemon.c
35
statemon.c
@ -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
|
||||
*
|
||||
@ -83,7 +83,7 @@ static int ExeCallback(int iEvent, void *pEvent, void *pUser)
|
||||
}
|
||||
|
||||
if (iEvent == BATCHSTART) {
|
||||
snprintf(pBueffel, 131, "exe %s", name);
|
||||
snprintf(pBueffel, 131, "exe %s", name);
|
||||
InvokeCallBack(self->pCall, STSTART, pBueffel);
|
||||
return 1;
|
||||
}
|
||||
@ -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);
|
||||
|
@ -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) {
|
||||
|
100
statusfile.c
100
statusfile.c
@ -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);
|
||||
|
@ -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
3
task.c
@ -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);
|
||||
}
|
||||
|
42
tasub.c
42
tasub.c
@ -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",
|
||||
@ -2148,7 +2164,7 @@ int TasUBWrapper(SConnection * pCon, SicsInterp * pSics, void *pData,
|
||||
}
|
||||
} else {
|
||||
snprintf(pBueffel, 131, "ERROR: subcommand %s to %s not defined",
|
||||
argv[1], argv[0]);
|
||||
argv[1], argv[0]);
|
||||
SCWrite(pCon, pBueffel, eError);
|
||||
return 0;
|
||||
}
|
||||
|
3
tasub.h
3
tasub.h
@ -29,13 +29,14 @@
|
||||
int mustDrive;
|
||||
int mustDriveQ;
|
||||
pMotor motors[12];
|
||||
char motname[12][32];
|
||||
tasReflection r1, r2;
|
||||
pIDrivable mono;
|
||||
long monoTaskID;
|
||||
void *monoData;
|
||||
int ubValid;
|
||||
int silent;
|
||||
int stopFixed; /* flag to stop multiple fixed messages in scans*/
|
||||
int stopFixed; /* flag to stop multiple fixed messages in scans*/
|
||||
char *updater;
|
||||
long groupID;
|
||||
}tasUB, *ptasUB;
|
||||
|
@ -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.
|
||||
#
|
||||
|
@ -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
19
trace.h
@ -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
|
||||
|
Reference in New Issue
Block a user