From 55eb873873ee7206164d76d3a488ee392958053c Mon Sep 17 00:00:00 2001 From: Douglas Clowes Date: Fri, 25 May 2007 16:46:58 +1000 Subject: [PATCH] replaced by AsyncQueue r1991 | dcl | 2007-05-25 16:46:58 +1000 (Fri, 25 May 2007) | 2 lines --- multichan.c | 735 ---------------------------------------------------- multichan.h | 48 ---- 2 files changed, 783 deletions(-) delete mode 100644 multichan.c delete mode 100644 multichan.h diff --git a/multichan.c b/multichan.c deleted file mode 100644 index ead83cf1..00000000 --- a/multichan.c +++ /dev/null @@ -1,735 +0,0 @@ -/* - * M U L T I C H A N - * - * This module manages communications on a multi-channel controller. - * - * A multi-channel controller is one where multiple channels or units are on a - * single controller and share a single command channel. - * - * Douglas Clowes, February 2007 - * - */ - -#include -#include -#include -#include -#include -#include -#include "network.h" -#include "multichan.h" -#include "nwatch.h" - -typedef struct __MultiChanController MultiChanController, *pMultiChanController; - -typedef struct __mcc_command MC_Cmd, *pMC_Cmd; - -struct __mcc_command { - pMC_Cmd next; - void* cntx; - MCC_Transmit tx; - MCC_Receive rx; - pMultiChan unit; - int timeout; - int retries; -}; - -struct __MultiChan { - pMultiChan next; - pMultiChanController mcc; - MCC_Notify notify_func; - void* notify_cntx; -}; - -struct __MultiChanController { - pObjectDescriptor pDes; - char* mcc_name; - char* pHost; - int iPort; - int iDelay; /* intercommand delay in milliseconds */ - int timeout; - int retries; - struct timeval tvLastCmd; /* time of completion of last command */ - int unit_count; /* number of units connected */ - pMultiChan units; /* head of unit chain */ - prs232 rs232c; /* associated RS232 controller object */ - pMC_Cmd command_head; /* first/next command in queue */ - pMC_Cmd command_tail; /* last command in queue */ - pNWContext nw_ctx; /* NetWait context handle */ - pNWTimer nw_tmr; /* NetWait timer handle */ - mkChannel* pSock; /* socket address */ -}; - -static pMultiChanController mcc_array[FD_SETSIZE]; -static int mcc_index = 0; - -/* ---------------------------- Local ------------------------------------ - CreateSocketAdress stolen from Tcl. Thanks to John Ousterhout -*/ - -static int -CreateSocketAdress( - struct sockaddr_in *sockaddrPtr, /* Socket address */ - char *host, /* Host. NULL implies INADDR_ANY */ - int port) /* Port number */ -{ - struct hostent *hostent; /* Host database entry */ - struct in_addr addr; /* For 64/32 bit madness */ - - (void) memset((char *) sockaddrPtr, '\0', sizeof(struct sockaddr_in)); - sockaddrPtr->sin_family = AF_INET; - sockaddrPtr->sin_port = htons((unsigned short) (port & 0xFFFF)); - if (host == NULL) { - addr.s_addr = INADDR_ANY; - } else { - hostent = gethostbyname(host); - if (hostent != NULL) { - memcpy((char *) &addr, - (char *) hostent->h_addr_list[0], (size_t) hostent->h_length); - } else { - addr.s_addr = inet_addr(host); - if (addr.s_addr == (unsigned long)-1) { - return 0; /* error */ - } - } - } - /* - * There is a rumor that this assignment may require care on - * some 64 bit machines. - */ - - sockaddrPtr->sin_addr.s_addr = addr.s_addr; - return 1; -} - -static void MC_Notify(pMultiChanController self, int event) -{ - pMultiChan unit; - for (unit = self->units; unit; unit = unit->next) - if (unit->notify_func != NULL) - unit->notify_func(unit->notify_cntx, event); -} - -static int MC_Reconnect(pMultiChanController self) -{ - int iRet; - int sock; - int flag = 1; - char line[132]; - - iRet = NETReconnect(self->pSock); - if (iRet <= 0) { - snprintf(line, 132, "Disconnect on MultiChan '%s'", self->mcc_name); - SICSLogWrite(line, eStatus); - MC_Notify(self, MCC_DISCONNECT); - return iRet; - } - snprintf(line, 132, "Reconnect on MultiChan '%s'", self->mcc_name); - SICSLogWrite(line, eStatus); - MC_Notify(self, MCC_RECONNECT); - return 1; -} - - -static int CommandTimeout(void* cntx, int mode); - -static int StartCommand(pMultiChanController self) -{ - pMC_Cmd myCmd = self->command_head; - mkChannel* sock = self->pSock; - - if (myCmd == NULL) - return OKOK; - - /* - * Remove any old command timeout timer - */ - if (self->nw_tmr) - NetWatchRemoveTimer(self->nw_tmr); - - /* - * Implement the inter-command delay - */ - if (self->iDelay) { - struct timeval now, when; - gettimeofday(&now, NULL); - if (self->tvLastCmd.tv_sec == 0) - self->tvLastCmd = now; - when.tv_sec = self->tvLastCmd.tv_sec; - when.tv_usec = self->tvLastCmd.tv_usec + 1000 * self->iDelay; - if (when.tv_usec >= 1000000) { - when.tv_sec += when.tv_usec / 1000000; - when.tv_usec %= 1000000; - } - if (when.tv_sec > now.tv_sec || - (when.tv_sec == now.tv_sec && when.tv_usec > now.tv_usec)) { - 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, - CommandTimeout, self); - return OKOK; - } - } - - /* - * Discard any input before sending command - */ - while (NETAvailable(sock, 0)) { - char reply[1]; - int iRet; - iRet = NETRead(sock, reply, 1, 0); - if (iRet < 0) { /* TODO: EOF */ - iRet = MC_Reconnect(self); - if (iRet == 0) - return 0; - } - } - /* - * Add a new command timeout timer - */ - if (myCmd->timeout > 0) - NetWatchRegisterTimer(&self->nw_tmr, myCmd->timeout, - CommandTimeout, self); - else - NetWatchRegisterTimer(&self->nw_tmr, 30000, - CommandTimeout, self); - return myCmd->tx(myCmd->cntx); -} - -static int QueCommand(pMultiChanController self, pMC_Cmd cmd) -{ - /* - * If the command queue is empty, start transmission - */ - if (self->command_head == NULL) { - self->command_head = self->command_tail = cmd; - StartCommand(self); - } else { - self->command_tail->next = cmd; - self->command_tail = cmd; - } - return 1; -} - -static int PopCommand(pMultiChanController self) -{ - pMC_Cmd myCmd = self->command_head; - if (self->nw_tmr) - NetWatchRemoveTimer(self->nw_tmr); - self->nw_tmr = 0; - gettimeofday(&self->tvLastCmd, NULL); - /* - * If this is not the last in queue, start transmission - */ - if (myCmd->next) { - pMC_Cmd pNew = myCmd->next; - self->command_head = pNew; - StartCommand(self); - } - else - self->command_head = self->command_tail = NULL; - free(myCmd); - return 1; -} - -static int CommandTimeout(void* cntx, int mode) -{ - pMultiChanController self = (pMultiChanController) cntx; - pMC_Cmd myCmd = self->command_head; - self->nw_tmr = 0; - if (myCmd->retries > 0) { - --myCmd->retries; - StartCommand(self); - } - else { - int iRet; - iRet = myCmd->rx(myCmd->cntx, MCC_TIMEOUT); - if (iRet == MCC_POP_CMD) - PopCommand(self); /* remove command */ - else if (iRet == MCC_RETRY_CMD) - StartCommand(self); /* restart command */ - else if (iRet == MCC_RECONNECT) - MC_Reconnect(self); - } - return 1; -} - -static int MyCallback(void* context, int mode) -{ - pMultiChanController self = (pMultiChanController) context; - - if (mode & nwatch_read) { - int iRet; - char reply[1]; - - iRet = NETRead(self->pSock, reply, 1, 0); - if (iRet < 0) { /* TODO: EOF */ - iRet = MC_Reconnect(self); - if (iRet <= 0) - return iRet; - /* restart the command */ - StartCommand(self); - return 1; - } - if (iRet == 0) { /* TODO: timeout or error */ - return 0; - } else { - pMC_Cmd myCmd = self->command_head; - if (myCmd) { - iRet = myCmd->rx(myCmd->cntx, reply[0]); - if (iRet == MCC_POP_CMD) /* end of command */ - PopCommand(self); - else if (iRet == 0) /* end of command */ - PopCommand(self); - else if (iRet < 0) /* TODO: error */ - ; - } - } - } - return 1; -} - -int MultiChanReconnect(pMultiChan unit) -{ - int iRet; - assert(unit); - assert(unit->mcc); - iRet = MC_Reconnect(unit->mcc); - /* TODO: handle in-progress */ - return iRet; -} - -mkChannel* MultiChanGetSocket(pMultiChan unit) -{ - assert(unit); - assert(unit->mcc); - return unit->mcc->pSock; -} - -int MultiChanEnque(pMultiChan unit, void* context, MCC_Transmit tx, MCC_Receive rx) -{ - pMC_Cmd myCmd = NULL; - - myCmd = (pMC_Cmd) malloc(sizeof(MC_Cmd)); - /* TODO: check malloc */ - memset(myCmd, 0, sizeof(MC_Cmd)); - myCmd->cntx = context; - myCmd->tx = tx; - myCmd->rx = rx; - myCmd->unit = unit; - myCmd->timeout = unit->mcc->timeout; - myCmd->retries = unit->mcc->retries; - return QueCommand(unit->mcc, myCmd); -} - -int MultiChanWrite(pMultiChan unit, void* buffer, int buflen) -{ - int iRet; - mkChannel* sock; - assert(unit); - assert(unit->mcc); - sock = MultiChanGetSocket(unit); - iRet = NETWrite(sock, buffer, buflen); - /* TODO handle errors */ - if (iRet < 0) { /* TODO: EOF */ - iRet = MC_Reconnect(unit->mcc); - if (iRet == 0) - return 0; - } - return 1; -} - -void MultiChanSetNotify(pMultiChan unit, void* context, MCC_Notify notify) -{ - assert(unit); - unit->notify_func = notify; - unit->notify_cntx = context; -} - -int MultiChanGetDelay(pMultiChan unit) -{ - assert(unit); - return unit->mcc->iDelay; -} - -int MultiChanSetDelay(pMultiChan unit, int iDelay) -{ - int old_iDelay; - assert(unit); - old_iDelay = unit->mcc->iDelay; - unit->mcc->iDelay = iDelay; - return old_iDelay; -} - -int MultiChanGetTimeout(pMultiChan unit) -{ - assert(unit); - return unit->mcc->timeout; -} - -int MultiChanSetTimeout(pMultiChan unit, int timeout) -{ - int old_timeout; - assert(unit); - old_timeout = unit->mcc->timeout; - unit->mcc->timeout = timeout; - return old_timeout; -} - -int MultiChanGetRetries(pMultiChan unit) -{ - assert(unit); - return unit->mcc->retries; -} - -int MultiChanSetRetries(pMultiChan unit, int retries) -{ - int old_retries; - assert(unit); - old_retries = unit->mcc->retries; - unit->mcc->retries = retries; - return old_retries; -} - -int MultiChanAction(SConnection *pCon, SicsInterp *pSics, - void *pData, int argc, char *argv[]) -{ - char line[132]; - pMultiChanController self = (pMultiChanController) pData; - if (argc > 1) { - if (strcasecmp(argv[1], "reconnect") == 0) { - MC_Reconnect(self); - return OKOK; - } - if (strcasecmp(argv[1], "delay") == 0) { - if (argc > 2) { - int delay; - int iRet; - iRet = sscanf(argv[2], "%d", &delay); - if (iRet != 1) { - snprintf(line, 132, "Invalid argument: %s", argv[2]); - SCWrite(pCon, line, eError); - return 0; - } - else { - if (delay < 0 || delay > 30000) { - snprintf(line, 132, "Value out of range: %d", delay); - SCWrite(pCon, line, eError); - return 0; - } - self->iDelay = delay; - return OKOK; - } - } - else { - snprintf(line, 132, "%s.delay = %d", argv[0], self->iDelay); - SCWrite(pCon, line, eStatus); - return OKOK; - } - return OKOK; - } - if (strcasecmp(argv[1], "timeout") == 0) { - if (argc > 2) { - int timeout; - int iRet; - iRet = sscanf(argv[2], "%d", &timeout); - if (iRet != 1) { - snprintf(line, 132, "Invalid argument: %s", argv[2]); - SCWrite(pCon, line, eError); - return 0; - } - else { - if (timeout < 0 || timeout > 30000) { - snprintf(line, 132, "Value out of range: %d", timeout); - SCWrite(pCon, line, eError); - return 0; - } - self->timeout = timeout; - return OKOK; - } - } - else { - snprintf(line, 132, "%s.timeout = %d", argv[0], self->timeout); - SCWrite(pCon, line, eStatus); - return OKOK; - } - return OKOK; - } - if (strcasecmp(argv[1], "retries") == 0) { - if (argc > 2) { - int retries; - int iRet; - iRet = sscanf(argv[2], "%d", &retries); - if (iRet != 1) { - snprintf(line, 132, "Invalid argument: %s", argv[2]); - SCWrite(pCon, line, eError); - return 0; - } - else { - if (retries < 0 || retries > 30000) { - snprintf(line, 132, "Value out of range: %d", retries); - SCWrite(pCon, line, eError); - return 0; - } - self->retries = retries; - return OKOK; - } - } - else { - snprintf(line, 132, "%s.retries = %d", argv[0], self->retries); - SCWrite(pCon, line, eStatus); - return OKOK; - } - return OKOK; - } - } - snprintf(line, 132, "%s does not understand %s", argv[0], argv[1]); - SCWrite(pCon, line, eError); - return 0; -} - -static pMultiChanController MC_Create(const char* host, const char* port) -{ - int i; - pMultiChanController self = NULL; - prs232 ctlr = NULL; - mkChannel* channel = NULL; - - if (host == NULL) - return NULL; - - /* try the MCC with this name */ - self = (pMultiChanController) FindCommandData(pServ->pSics, host, "MultiChan"); - - /* try the RS232 Controller with this name */ - if (self == NULL && port == NULL) { - ctlr = (prs232) FindCommandData(pServ->pSics, host, "RS232 Controller"); - if(ctlr == NULL) { - char line[132]; - snprintf(line, 132, "ERROR: RS232 Controller '%s' is not found in MultiChan", host); - SICSLogWrite(line, eError); - return NULL; - } - channel = ctlr->pSock; - if (channel == NULL) { - char line[132]; - snprintf(line, 132, "ERROR: RS232 Controller '%s' is not connected in MultiChan", host); - SICSLogWrite(line, eError); - return NULL; - } - /* look for mcc with same controller */ - for (i = 0; i < mcc_index; ++i) - if (mcc_array[i]->rs232c == ctlr) { - self = mcc_array[i]; - break; - } - } - - /* try host and port */ - if (self == NULL && ctlr == NULL) { - int port_no = atoi(port); - if (port_no == 0) { - struct servent *sp=NULL; - sp = getservbyname(port, NULL); - if (sp) - port_no = ntohs(sp->s_port); - } - if (port_no > 0) { - struct sockaddr_in sa; - if (CreateSocketAdress(&sa, host, port_no)) { - /* look for mcc with same address */ - for (i = 0; i < mcc_index; ++i) - if (mcc_array[i]->pSock->adresse.sin_port == sa.sin_port - && mcc_array[i]->pSock->adresse.sin_addr.s_addr == sa.sin_addr.s_addr) { - self = mcc_array[i]; - break; - } - } - if (self == NULL) { - channel = NETConnectWithFlags(host, port_no, 0); - /* TODO */ - } - } - } - - if (self == NULL) { - if (ctlr == NULL && channel == NULL) - return NULL; - - self = (pMultiChanController) malloc(sizeof(MultiChanController)); - if (self == NULL) - return NULL; - memset(self, 0, sizeof(MultiChanController)); - self->rs232c = ctlr; - self->pSock = channel; - self->pDes = CreateDescriptor("MultiChan"); - mcc_array[mcc_index++] = self; - } - - for (i = 0; i < mcc_index; ++i) - if (mcc_array[i] == self) { - break; - } - if (i == mcc_index) - mcc_array[mcc_index++] = self; - - return self; -} - -static int MC_Init(pMultiChanController self) -{ - /* TODO: Init the controller */ - if (self->nw_ctx == NULL) - NetWatchRegisterCallback(&self->nw_ctx, - self->pSock->sockid, - MyCallback, - self); - return 1; -} - -static void MC_Kill(void* pData) -{ - int i; - pMultiChanController self = (pMultiChanController) pData; - for (i = 0; i < mcc_index; ++i) - if (mcc_array[i] == self) { - --mcc_index; - if (mcc_index > 0) - mcc_array[i] = mcc_array[mcc_index]; - if (self->nw_ctx) - NetWatchRemoveCallback(self->nw_ctx); - if (self->nw_tmr) - NetWatchRemoveTimer(self->nw_tmr); - if (self->mcc_name) - free(self->mcc_name); - if (self->rs232c == NULL) { - NETClosePort(self->pSock); - free(self->pSock); - } - free(self); - return; - } -} - -/* - * \brief make a multichannel controller from the command line - */ -int MultiChanFactory(SConnection *pCon, SicsInterp *pSics, - void *pData, int argc, char *argv[]) -{ - pMultiChanController pNew = NULL; - int iRet, status; - char pError[256]; - - if(argc < 3) - { - SCWrite(pCon,"ERROR: insufficient no of arguments to MultiChanFactory", - eError); - return 0; - } - - /* try to find an existing mcc with this name */ - pNew = (pMultiChanController) FindCommandData(pServ->pSics, argv[1], "MultiChan"); - if (pNew != NULL) { - char line[132]; - snprintf(line, 132, "ERROR: MultiChan '%s' already exists", argv[1]); - SCWrite(pCon, line, eError); - return 1; - } - - /* - create data structure and open port - */ - if (argc > 3) - pNew = MC_Create(argv[2], argv[3]); - else - pNew = MC_Create(argv[2], NULL) ; - - if(!pNew) - { - SCWrite(pCon,"ERROR: failed to create MultiChan in MultiChanFactory",eError); - return 0; - } - if (pNew->mcc_name) - free(pNew->mcc_name); - pNew->mcc_name = strdup(argv[1]); - - status = MC_Init(pNew); - if(status != 1) - { - sprintf(pError,"ERROR: failed to connect to %s at port %d", - pNew->pHost, pNew->iPort); - SCWrite(pCon,pError,eError); - } - - /* - create the command - */ - iRet = AddCommand(pSics, argv[1], MultiChanAction, MC_Kill, pNew); - if(!iRet) - { - sprintf(pError,"ERROR: duplicate command %s not created", argv[1]); - SCWrite(pCon,pError,eError); - MC_Kill(pNew); - return 0; - } - return 1; -} - -/* - * \brief make a multichannel controller from a named rs232 controller - * - * \param name the name of the SICS "RS232 Controller" object - * \param handle the handle to the multichannel controller object - * \return 0 for FAILURE, 1 for SUCCESS - */ -int MultiChanCreateHost(const char* host, const char* port, pMultiChan* handle) -{ - int status; - pMultiChanController self = NULL; - pMultiChan unit = NULL; - - *handle = NULL; - - self = MC_Create(host, port); - if (self == NULL) - return 0; - status = MC_Init(self); - - unit = (pMultiChan) malloc(sizeof(MultiChan)); - /* TODO: check malloc failure */ - memset(unit, 0, sizeof(MultiChan)); - ++self->unit_count; - unit->mcc = self; - unit->next = self->units; - self->units = unit; - *handle = unit; - return 1; -} - -int MultiChanCreate(const char* host, pMultiChan* handle) { - return MultiChanCreateHost(host, NULL, handle); -} - -int MultiChanDestroy(pMultiChan unit) -{ - assert(unit); - assert(unit->mcc); - pMultiChanController self = unit->mcc; - pMultiChan* pNxt = &self->units; - while (*pNxt) { - if (*pNxt == unit) { - *pNxt = (*pNxt)->next; - break; - } - pNxt = &(*pNxt)->next; - } - --self->unit_count; - if (self->unit_count <= 0) { - MC_Kill(self); - } - free(unit); - return 1; -} - diff --git a/multichan.h b/multichan.h deleted file mode 100644 index a901cc2e..00000000 --- a/multichan.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * M U L T I C H A N - * - * This module manages communications on a multi-channel controller. - * - * A multi-channel controller is one where multiple channels or units are on a - * single controller and share a single command channel. - * - * Douglas Clowes, February 2007 - * - */ -#ifndef SICSMULTICHAN -#define SICSMULTICHAN - -#include - -/* transitional definitions*/ -#define MCC_TIMEOUT AQU_TIMEOUT -#define MCC_DISCONNECT AQU_DISCONNECT -#define MCC_RECONNECT AQU_RECONNECT -#define MCC_RETRY_CMD AQU_RETRY_CMD -#define MCC_POP_CMD AQU_POP_CMD -#define MCC_Transmit AQU_Transmit -#define MCC_Receive AQU_Receive -#define MCC_Notify AQU_Notify - -#define __MultiChan __AsyncUnit -#define MultiChan AsyncUnit -#define pMultiChan pAsyncUnit - -#define MultiChanCreate AsyncUnitCreate -#define MultiChanCreateHost AsyncUnitCreateHost -#define MultiChanDestroy AsyncUnitDestroy -#define MultiChanReconnect AsyncUnitReconnect -#define MultiChanGetSocket AsyncUnitGetSocket -#define MultiChanEnqueTxn AsyncUnitEnqueTxn -#define MultiChanEnque AsyncUnitEnque -#define MultiChanWrite AsyncUnitWrite -#define MultiChanSetNotify AsyncUnitSetNotify -#define MultiChanGetDelay AsyncUnitGetDelay -#define MultiChanSetDelay AsyncUnitSetDelay -#define MultiChanGetTimeout AsyncUnitGetTimeout -#define MultiChanSetTimeout AsyncUnitSetTimeout - -#define MultiChanFactory AsyncQueueFactory -#define MultiChanAction AsyncQueueAction - -#endif /* SICSMULTICHAN */