many, many changes
This commit is contained in:
+7
-2
@@ -20,7 +20,7 @@ LIBSRCS += cacNotify.cpp
|
||||
LIBSRCS += cacNotifyIO.cpp
|
||||
LIBSRCS += cacServiceList.cpp
|
||||
LIBSRCS += access.cpp
|
||||
LIBSRCS += processThread.cpp
|
||||
LIBSRCS += recvProcessThread.cpp
|
||||
LIBSRCS += iocinf.cpp
|
||||
LIBSRCS += convert.cpp
|
||||
LIBSRCS += test_event.cpp
|
||||
@@ -38,7 +38,6 @@ LIBSRCS += netReadNotifyIO.cpp
|
||||
LIBSRCS += netWriteNotifyIO.cpp
|
||||
LIBSRCS += netSubscription.cpp
|
||||
LIBSRCS += cac.cpp
|
||||
LIBSRCS += conn.cpp
|
||||
LIBSRCS += tcpSendWatchdog.cpp
|
||||
LIBSRCS += tcpRecvWatchdog.cpp
|
||||
LIBSRCS += bhe.cpp
|
||||
@@ -50,6 +49,12 @@ LIBSRCS += syncgrp.cpp
|
||||
LIBSRCS += CASG.cpp
|
||||
LIBSRCS += syncGroupNotify.cpp
|
||||
LIBSRCS += localHostName.cpp
|
||||
LIBSRCS += claimsPendingIIU.cpp
|
||||
LIBSRCS += claimMsgCache.cpp
|
||||
LIBSRCS += comQueRecv.cpp
|
||||
LIBSRCS += comQueSend.cpp
|
||||
LIBSRCS += cacPrivate.cpp
|
||||
LIBSRCS += hostNameCache.cpp
|
||||
|
||||
LIBRARY=ca
|
||||
|
||||
|
||||
+22
-18
@@ -25,6 +25,7 @@
|
||||
|
||||
#include "iocinf.h"
|
||||
#include "oldAccess.h"
|
||||
#include "cac_IL.h"
|
||||
|
||||
threadPrivateId caClientContextId;
|
||||
|
||||
@@ -229,7 +230,7 @@ int epicsShareAPI ca_search_and_connect (const char *name_str, chid *chanptr,
|
||||
int caStatus;
|
||||
cac *pcac;
|
||||
|
||||
caStatus = fetchClientContext (&pcac);
|
||||
caStatus = fetchClientContext ( &pcac );
|
||||
if ( caStatus != ECA_NORMAL ) {
|
||||
return caStatus;
|
||||
}
|
||||
@@ -238,16 +239,23 @@ int epicsShareAPI ca_search_and_connect (const char *name_str, chid *chanptr,
|
||||
return ECA_EMPTYSTR;
|
||||
}
|
||||
|
||||
pChan = new oldChannel (conn_func, puser);
|
||||
pChan = new oldChannel ( conn_func, puser );
|
||||
if ( ! pChan ) {
|
||||
return ECA_ALLOCMEM;
|
||||
}
|
||||
|
||||
// we must set *chanptr here before we are 100% certain that
|
||||
// the channel can be created in case *chanptr is inside
|
||||
// of their structure at address puser and they reference
|
||||
// it in a connection handler that is called by createChannelIO()
|
||||
chid tmp = *chanptr;
|
||||
*chanptr = pChan;
|
||||
|
||||
if ( pcac->createChannelIO ( name_str, *pChan ) ) {
|
||||
*chanptr = pChan;
|
||||
return ECA_NORMAL;
|
||||
}
|
||||
else {
|
||||
*chanptr = tmp;
|
||||
pChan->destroy ();
|
||||
return ECA_ALLOCMEM;
|
||||
}
|
||||
@@ -428,7 +436,7 @@ int epicsShareAPI ca_pend (ca_real timeout, int early)
|
||||
cac *pcac;
|
||||
int status;
|
||||
|
||||
status = fetchClientContext (&pcac);
|
||||
status = fetchClientContext ( &pcac );
|
||||
if ( status != ECA_NORMAL ) {
|
||||
return status;
|
||||
}
|
||||
@@ -660,16 +668,16 @@ int epicsShareAPI ca_replace_printf_handler (caPrintfFunc *ca_printf_func)
|
||||
/*
|
||||
* ca_printf()
|
||||
*/
|
||||
int ca_printf (const char *pformat, ...)
|
||||
int ca_printf ( const char *pformat, ... )
|
||||
{
|
||||
va_list theArgs;
|
||||
int status;
|
||||
|
||||
va_start (theArgs, pformat);
|
||||
va_start ( theArgs, pformat );
|
||||
|
||||
status = ca_vPrintf (pformat, theArgs);
|
||||
status = ca_vPrintf ( pformat, theArgs );
|
||||
|
||||
va_end (theArgs);
|
||||
va_end ( theArgs );
|
||||
|
||||
return status;
|
||||
}
|
||||
@@ -677,31 +685,27 @@ int ca_printf (const char *pformat, ...)
|
||||
/*
|
||||
* ca_vPrintf()
|
||||
*/
|
||||
int ca_vPrintf (const char *pformat, va_list args)
|
||||
int ca_vPrintf ( const char *pformat, va_list args )
|
||||
{
|
||||
caPrintfFunc *ca_printf_func;
|
||||
|
||||
if ( caClientContextId ) {
|
||||
cac *pcac = (cac *) threadPrivateGet ( caClientContextId );
|
||||
if (pcac) {
|
||||
ca_printf_func = pcac->ca_printf_func;
|
||||
if ( pcac ) {
|
||||
return pcac->vPrintf ( pformat, args );
|
||||
}
|
||||
else {
|
||||
ca_printf_func = errlogVprintf;
|
||||
return ( *errlogVprintf ) ( pformat, args );
|
||||
}
|
||||
}
|
||||
else {
|
||||
ca_printf_func = errlogVprintf;
|
||||
return ( *errlogVprintf ) ( pformat, args );
|
||||
}
|
||||
|
||||
return (*ca_printf_func) ( pformat, args );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ca_field_type()
|
||||
*/
|
||||
short epicsShareAPI ca_field_type (chid pChan)
|
||||
short epicsShareAPI ca_field_type ( chid pChan )
|
||||
{
|
||||
return pChan->nativeType ();
|
||||
}
|
||||
|
||||
+1189
-1163
File diff suppressed because it is too large
Load Diff
+23
-5
@@ -1,15 +1,33 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "caDiagnostics.h"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
int main ( int argc, char **argv )
|
||||
{
|
||||
if(argc == 2){
|
||||
acctst(argv[1]);
|
||||
unsigned channelCount;
|
||||
unsigned repetitionCount;
|
||||
|
||||
if ( argc < 2 || argc > 4 ) {
|
||||
printf ( "usage: %s <chan name> [channel count] [repetition count]\n", argv[0] );
|
||||
}
|
||||
else{
|
||||
printf("usage: %s <chan name>\n", argv[0]);
|
||||
|
||||
if ( argc >= 3 ) {
|
||||
channelCount = atoi ( argv[2] );
|
||||
}
|
||||
else {
|
||||
channelCount = 20000;
|
||||
}
|
||||
|
||||
if ( argc >= 4 ) {
|
||||
repetitionCount = atoi ( argv[3] );
|
||||
}
|
||||
else {
|
||||
repetitionCount = 1;
|
||||
}
|
||||
|
||||
acctst ( argv[1], channelCount, repetitionCount );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
*
|
||||
* L O S A L A M O S
|
||||
* Los Alamos National Laboratory
|
||||
* Los Alamos, New Mexico 87545
|
||||
*
|
||||
* Copyright, 1986, The Regents of the University of California.
|
||||
*
|
||||
*
|
||||
* Author Jeffrey O. Hill
|
||||
* johill@lanl.gov
|
||||
* 505 665 1831
|
||||
*/
|
||||
|
||||
#ifndef baseIIU_ILh
|
||||
#define baseIIU_ILh
|
||||
|
||||
|
||||
#endif // baseIIU_ILh
|
||||
+9
-8
@@ -11,20 +11,21 @@
|
||||
*/
|
||||
|
||||
#include "iocinf.h"
|
||||
#include "nciu_IL.h"
|
||||
|
||||
baseNMIU::baseNMIU ( nciu &chanIn ) : chan (chanIn)
|
||||
baseNMIU::baseNMIU ( nciu &chanIn ) : chan ( chanIn )
|
||||
{
|
||||
this->chan.installIO ( *this );
|
||||
}
|
||||
|
||||
void baseNMIU::destroy ()
|
||||
{
|
||||
delete this;
|
||||
chanIn.ioInstall ( *this );
|
||||
}
|
||||
|
||||
baseNMIU::~baseNMIU ()
|
||||
{
|
||||
this->chan.uninstallIO ( *this );
|
||||
// private NOOP forces pool allocation
|
||||
}
|
||||
|
||||
void baseNMIU::destroy ()
|
||||
{
|
||||
this->chan.ioDestroy ( this->getId () );
|
||||
}
|
||||
|
||||
int baseNMIU::subscriptionMsg ()
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
|
||||
enum appendNumberFlag {appendNumber, dontAppendNumber};
|
||||
|
||||
int catime (char *channelName, unsigned channelCount, enum appendNumberFlag appNF);
|
||||
int catime ( char *channelName, unsigned channelCount, enum appendNumberFlag appNF );
|
||||
|
||||
int acctst (char *pname);
|
||||
int acctst ( char *pname, unsigned channelCount, unsigned repititionCount );
|
||||
|
||||
#define CATIME_OK 0
|
||||
#define CATIME_ERROR -1
|
||||
|
||||
+13
-9
@@ -74,14 +74,18 @@
|
||||
* environment variables "EPICS_CA_REPEATER_PORT" and
|
||||
* "EPICS_CA_SERVER_PORT"
|
||||
*/
|
||||
#define CA_PORT_BASE IPPORT_USERRESERVED + 56U
|
||||
#define CA_SERVER_PORT (CA_PORT_BASE+CA_PROTOCOL_VERSION*2u)
|
||||
#define CA_REPEATER_PORT (CA_PORT_BASE+CA_PROTOCOL_VERSION*2u+1u)
|
||||
/* 1492(min of ethernet and 802.{2,3} MTU) - 20(IP) - 8(UDP) joh 8-6-97 */
|
||||
#define ETHERNET_MAX_UDP (1482u-20u-8u)
|
||||
#define MAX_UDP 1024u /* original MAX_UDP */
|
||||
#define MAX_TCP (MAX_UDP*16u) /* so waveforms fit */
|
||||
#define MAX_MSG_SIZE (MAX_TCP) /* the larger of tcp and udp max */
|
||||
#define CA_PORT_BASE IPPORT_USERRESERVED + 56U
|
||||
#define CA_SERVER_PORT (CA_PORT_BASE+CA_PROTOCOL_VERSION*2u)
|
||||
#define CA_REPEATER_PORT (CA_PORT_BASE+CA_PROTOCOL_VERSION*2u+1u)
|
||||
/*
|
||||
* 1500 (max of ethernet and 802.{2,3} MTU) - 20(IP) - 8(UDP)
|
||||
* (the MTU of Ethernet is currently independent of speed varient)
|
||||
*/
|
||||
#define ETHERNET_MAX_UDP ( 1500u - 20u - 8u )
|
||||
#define MAX_UDP_RECV ( 0xffff + 16u ) /* allow large frames to be received in the future */
|
||||
#define MAX_UDP_SEND 1024u /* original MAX_UDP */
|
||||
#define MAX_TCP ( 1024 * 16u ) /* so waveforms fit */
|
||||
#define MAX_MSG_SIZE ( MAX_TCP ) /* the larger of tcp and udp max */
|
||||
|
||||
/*
|
||||
* architecture independent types
|
||||
@@ -118,7 +122,7 @@ typedef ca_uint32_t caResId;
|
||||
#define CA_PROTO_HOST_NAME 21u /* CA V4.1 identify client */
|
||||
#define CA_PROTO_ACCESS_RIGHTS 22u /* CA V4.2 asynch access rights chg */
|
||||
#define CA_PROTO_ECHO 23u /* CA V4.3 connection verify */
|
||||
#define REPEATER_REGISTER 24u /* registr for repeater fan out */
|
||||
#define REPEATER_REGISTER 24u /* register for repeater fan out */
|
||||
#define CA_PROTO_SIGNAL 25u /* knock the server out of select */
|
||||
#define CA_PROTO_CLAIM_CIU_FAILED 26u /* unable to create chan resource in server */
|
||||
#define CA_PROTO_SERVER_DISCONN 27u /* server deletes PV (or channel) */
|
||||
|
||||
@@ -1,75 +0,0 @@
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* caExtraEventLabor ()
|
||||
*/
|
||||
LOCAL void caExtraEventLabor (void *pArg)
|
||||
{
|
||||
cac *pcac = (cac *) pArg;
|
||||
dbcaPutNotify *ppnb;
|
||||
struct event_handler_args args;
|
||||
|
||||
while (TRUE) {
|
||||
semTakeStatus semStatus;
|
||||
|
||||
/*
|
||||
* independent lock used here in order to
|
||||
* avoid any possibility of blocking
|
||||
* the database (or indirectly blocking
|
||||
* one client on another client).
|
||||
*/
|
||||
semStatus = semMutexTakeTimeout (pcac->localIIU.putNotifyLock, 60.0 /* sec */);
|
||||
if (semStatus!=semTakeOK) {
|
||||
ca_printf ("cac: put notify deadlock condition detected\n");
|
||||
(*pcac->localIIU.pdbAdapter->p_db_post_extra_labor) (pcac->localIIU.evctx);
|
||||
break;
|
||||
}
|
||||
ppnb = (dbcaPutNotify *) ellGet (&pcac->localIIU.putNotifyQue);
|
||||
semMutexGive (pcac->localIIU.putNotifyLock);
|
||||
|
||||
/*
|
||||
* break to loop exit
|
||||
*/
|
||||
if (!ppnb) {
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* setup arguments and call user's function
|
||||
*/
|
||||
args.usr = ppnb->caUserArg;
|
||||
args.chid = ppnb->dbPutNotify.usrPvt;
|
||||
#error type must be an external type
|
||||
args.type = ppnb->dbPutNotify.dbrType;
|
||||
args.count = ppnb->dbPutNotify.nRequest;
|
||||
args.dbr = NULL;
|
||||
if (ppnb->dbPutNotify.status) {
|
||||
if (ppnb->dbPutNotify.status == S_db_Blocked) {
|
||||
args.status = ECA_PUTCBINPROG;
|
||||
}
|
||||
else {
|
||||
args.status = ECA_PUTFAIL;
|
||||
}
|
||||
}
|
||||
else {
|
||||
args.status = ECA_NORMAL;
|
||||
}
|
||||
|
||||
pcac->lock ();
|
||||
(*ppnb->caUserCallback) (args);
|
||||
pcac->unlock ();
|
||||
|
||||
ppnb->busy = FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* wakeup the TCP thread if it is waiting for a cb to complete
|
||||
*/
|
||||
semBinaryGive (pcac->ca_blockSem);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
+380
-195
@@ -39,11 +39,11 @@ static void cacInitRecursionLock ( void * dummy )
|
||||
// cac::cac ()
|
||||
//
|
||||
cac::cac ( bool enablePreemptiveCallbackIn ) :
|
||||
beaconTable ( 1024 ),
|
||||
endOfBCastList ( 0 ),
|
||||
ipToAEngine ( "caIPAddrToAsciiEngine" ),
|
||||
ioTable ( 1024 ),
|
||||
chanTable ( 1024 ),
|
||||
sgTable ( 128 ),
|
||||
beaconTable ( 1024 ),
|
||||
fdRegFunc ( 0 ),
|
||||
fdRegArg ( 0 ),
|
||||
pudpiiu ( 0 ),
|
||||
@@ -81,8 +81,7 @@ cac::cac ( bool enablePreemptiveCallbackIn ) :
|
||||
throwWithLocation ( caErrorCode (ECA_ALLOCMEM) );
|
||||
}
|
||||
|
||||
ellInit (&this->putCvrtBuf);
|
||||
this->ca_printf_func = errlogVprintf;
|
||||
this->pVPrintfFunc = errlogVprintf;
|
||||
this->ca_exception_func = ca_default_exception_handler;
|
||||
this->ca_exception_arg = NULL;
|
||||
this->readSeq = 0u;
|
||||
@@ -103,44 +102,41 @@ cac::cac ( bool enablePreemptiveCallbackIn ) :
|
||||
if ( gunRet != osiGetUserNameSuccess ) {
|
||||
tmp[0] = '\0';
|
||||
}
|
||||
len = strlen (tmp) + 1;
|
||||
this->ca_pUserName = (char *) malloc ( len );
|
||||
if ( ! this->ca_pUserName ) {
|
||||
len = strlen ( tmp ) + 1;
|
||||
this->pUserName = new char [len];
|
||||
if ( ! this->pUserName ) {
|
||||
semBinaryDestroy (this->ca_blockSem);
|
||||
throwWithLocation ( caErrorCode (ECA_ALLOCMEM) );
|
||||
}
|
||||
strncpy (this->ca_pUserName, tmp, len);
|
||||
strncpy ( this->pUserName, tmp, len );
|
||||
}
|
||||
|
||||
this->programBeginTime = osiTime::getCurrent ();
|
||||
|
||||
status = envGetDoubleConfigParam (&EPICS_CA_CONN_TMO, &this->ca_connectTMO);
|
||||
if (status) {
|
||||
this->ca_connectTMO = CA_CONN_VERIFY_PERIOD;
|
||||
status = envGetDoubleConfigParam ( &EPICS_CA_CONN_TMO, &this->connTMO );
|
||||
if ( status ) {
|
||||
this->connTMO = CA_CONN_VERIFY_PERIOD;
|
||||
ca_printf (
|
||||
"EPICS \"%s\" float fetch failed\n",
|
||||
"EPICS \"%s\" double fetch failed\n",
|
||||
EPICS_CA_CONN_TMO.name);
|
||||
ca_printf (
|
||||
"Setting \"%s\" = %f\n",
|
||||
"Defaulting \"%s\" = %f\n",
|
||||
EPICS_CA_CONN_TMO.name,
|
||||
this->ca_connectTMO);
|
||||
this->connTMO);
|
||||
}
|
||||
|
||||
this->ca_server_port =
|
||||
envGetInetPortConfigParam (&EPICS_CA_SERVER_PORT, CA_SERVER_PORT);
|
||||
|
||||
//
|
||||
// unfortunately, this must be created her in the
|
||||
// unfortunately, this must be created here in the
|
||||
// constructor, and not on demand (only when it is needed)
|
||||
// because the enable reference count must be
|
||||
// maintained whenever this object exists.
|
||||
//
|
||||
this->pProcThread = new processThread ( this );
|
||||
if ( ! this->pProcThread ) {
|
||||
throwWithLocation ( caErrorCode (ECA_ALLOCMEM) );
|
||||
this->pRecvProcThread = new recvProcessThread ( this );
|
||||
if ( ! this->pRecvProcThread ) {
|
||||
throwWithLocation ( caErrorCode ( ECA_ALLOCMEM ) );
|
||||
}
|
||||
else if ( this->enablePreemptiveCallback ) {
|
||||
// only after this->pProcThread is valid
|
||||
// only after this->pRecvProcThread is valid
|
||||
this->enableCallbackPreemption ();
|
||||
}
|
||||
}
|
||||
@@ -170,19 +166,15 @@ cac::~cac ()
|
||||
// make certain that process thread isnt deleting
|
||||
// tcpiiu objects at the same that this thread is
|
||||
//
|
||||
delete this->pProcThread;
|
||||
recvProcessThread *pTmp = this->pRecvProcThread;
|
||||
this->pRecvProcThread = 0;
|
||||
delete pTmp;
|
||||
|
||||
//
|
||||
// shutdown all tcp connections and wait for threads to exit
|
||||
//
|
||||
this->iiuListMutex.lock ();
|
||||
tsDLIterBD <tcpiiu> piiu ( this->iiuListIdle.first () );
|
||||
while ( piiu.valid () ) {
|
||||
tsDLIterBD <tcpiiu> pnext = piiu.itemAfter ();
|
||||
piiu->suicide ();
|
||||
piiu = pnext;
|
||||
}
|
||||
piiu = this->iiuListRecvPending.first ();
|
||||
tsDLIterBD <tcpiiu> piiu ( this->iiuList.first () );
|
||||
while ( piiu.valid () ) {
|
||||
tsDLIterBD <tcpiiu> pnext = piiu.itemAfter ();
|
||||
piiu->suicide ();
|
||||
@@ -207,21 +199,17 @@ cac::~cac ()
|
||||
delete this->pudpiiu;
|
||||
}
|
||||
|
||||
/* remove put convert block free list */
|
||||
ellFree ( &this->putCvrtBuf );
|
||||
|
||||
/* reclaim sync group resources */
|
||||
this->sgTable.destroyAllEntries ();
|
||||
|
||||
/*
|
||||
* free user name string
|
||||
*/
|
||||
if ( this->ca_pUserName ) {
|
||||
free ( this->ca_pUserName );
|
||||
if ( this->pUserName ) {
|
||||
delete [] this->pUserName;
|
||||
}
|
||||
|
||||
this->sgTable.destroyAllEntries ();
|
||||
this->beaconTable.destroyAllEntries ();
|
||||
|
||||
this->chanTable.destroyAllEntries ();
|
||||
this->ioTable.destroyAllEntries ();
|
||||
semBinaryDestroy ( this->ca_blockSem );
|
||||
|
||||
osiSockRelease ();
|
||||
@@ -229,59 +217,18 @@ cac::~cac ()
|
||||
delete this->pTimerQueue;
|
||||
}
|
||||
|
||||
void cac::safeDestroyNMIU (unsigned id)
|
||||
{
|
||||
this->defaultMutex.lock ();
|
||||
|
||||
baseNMIU *pIOBlock = this->ioTable.lookup (id);
|
||||
if ( pIOBlock ) {
|
||||
pIOBlock->destroy ();
|
||||
}
|
||||
|
||||
this->defaultMutex.unlock ();
|
||||
}
|
||||
|
||||
void cac::processRecvBacklog ()
|
||||
{
|
||||
tcpiiu *piiu;
|
||||
this->iiuListMutex.lock ();
|
||||
|
||||
while ( 1 ) {
|
||||
int status;
|
||||
unsigned bytesToProcess;
|
||||
tsDLIterBD <tcpiiu> piiu ( this->iiuList.first () );
|
||||
while ( piiu.valid () ) {
|
||||
tsDLIterBD <tcpiiu> pNext = piiu.itemAfter ();
|
||||
piiu->processIncomingAndDestroySelfIfDisconnected ();
|
||||
piiu = pNext;
|
||||
}
|
||||
|
||||
this->iiuListMutex.lock ();
|
||||
|
||||
piiu = this->iiuListRecvPending.get ();
|
||||
if ( ! piiu ) {
|
||||
this->iiuListMutex.unlock ();
|
||||
break;
|
||||
}
|
||||
|
||||
piiu->recvPending = false;
|
||||
this->iiuListIdle.add (*piiu);
|
||||
|
||||
this->iiuListMutex.unlock ();
|
||||
|
||||
if ( piiu->state == iiu_disconnected ) {
|
||||
delete piiu;
|
||||
continue;
|
||||
}
|
||||
|
||||
char *pProto = (char *) cacRingBufferReadReserveNoBlock
|
||||
(&piiu->recv, &bytesToProcess);
|
||||
while ( pProto ) {
|
||||
status = piiu->post_msg (pProto, bytesToProcess);
|
||||
if ( status == ECA_NORMAL ) {
|
||||
cacRingBufferReadCommit (&piiu->recv, bytesToProcess);
|
||||
cacRingBufferReadFlush (&piiu->recv);
|
||||
}
|
||||
else {
|
||||
delete piiu;
|
||||
}
|
||||
pProto = (char *) cacRingBufferReadReserveNoBlock
|
||||
(&piiu->recv, &bytesToProcess);
|
||||
}
|
||||
}
|
||||
this->iiuListMutex.unlock ();
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -293,12 +240,7 @@ void cac::flush ()
|
||||
* set the push pending flag on all virtual circuits
|
||||
*/
|
||||
this->iiuListMutex.lock ();
|
||||
tsDLIterBD<tcpiiu> piiu ( this->iiuListIdle.first () );
|
||||
while ( piiu.valid () ) {
|
||||
piiu->flush ();
|
||||
piiu++;
|
||||
}
|
||||
piiu = this->iiuListRecvPending.first ();
|
||||
tsDLIterBD <tcpiiu> piiu ( this->iiuList.first () );
|
||||
while ( piiu.valid () ) {
|
||||
piiu->flush ();
|
||||
piiu++;
|
||||
@@ -317,69 +259,47 @@ void cac::flush ()
|
||||
*/
|
||||
void cac::cleanUpPendIO ()
|
||||
{
|
||||
nciu *pchan;
|
||||
|
||||
this->defaultMutex.lock ();
|
||||
|
||||
this->readSeq++;
|
||||
this->pndrecvcnt = 0u;
|
||||
|
||||
if ( this->pudpiiu ) {
|
||||
tsDLIter <nciu> iter ( this->pudpiiu->chidList );
|
||||
while ( ( pchan = iter () ) ) {
|
||||
pchan->connectTimeoutNotify ();
|
||||
}
|
||||
}
|
||||
|
||||
this->defaultMutex.unlock ();
|
||||
|
||||
if ( this->pudpiiu ) {
|
||||
this->pudpiiu->connectTimeoutNotify ();
|
||||
}
|
||||
}
|
||||
|
||||
unsigned cac::connectionCount () const
|
||||
{
|
||||
unsigned count;
|
||||
|
||||
this->iiuListMutex.lock ();
|
||||
count = this->iiuListIdle.count () + this->iiuListRecvPending.count ();
|
||||
this->iiuListMutex.unlock ();
|
||||
return count;
|
||||
return this->iiuList.count ();
|
||||
}
|
||||
|
||||
void cac::show (unsigned level) const
|
||||
{
|
||||
this->defaultMutex.lock ();
|
||||
|
||||
if ( this->pudpiiu ) {
|
||||
this->pudpiiu->show (level);
|
||||
}
|
||||
|
||||
this->iiuListMutex.lock ();
|
||||
|
||||
tsDLIterConstBD <tcpiiu> piiu ( this->iiuListIdle.first () );
|
||||
while ( piiu.valid () ) {
|
||||
piiu->show (level);
|
||||
piiu++;
|
||||
}
|
||||
|
||||
piiu = this->iiuListRecvPending.first ();
|
||||
tsDLIterConstBD <tcpiiu> piiu ( this->iiuList.first () );
|
||||
while ( piiu.valid () ) {
|
||||
piiu->show (level);
|
||||
piiu++;
|
||||
}
|
||||
|
||||
this->iiuListMutex.unlock ();
|
||||
|
||||
this->defaultMutex.unlock ();
|
||||
}
|
||||
|
||||
void cac::installIIU ( tcpiiu &iiu )
|
||||
{
|
||||
this->iiuListMutex.lock ();
|
||||
iiu.recvPending = false;
|
||||
this->iiuListIdle.add (iiu);
|
||||
this->iiuList.add (iiu);
|
||||
this->iiuListMutex.unlock ();
|
||||
|
||||
this->defaultMutex.lock ();
|
||||
|
||||
if ( ! this->enablePreemptiveCallback && this->fdRegFunc ) {
|
||||
( * this->fdRegFunc )
|
||||
( (void *) this->fdRegArg, iiu.getSock (), TRUE );
|
||||
@@ -387,33 +307,14 @@ void cac::installIIU ( tcpiiu &iiu )
|
||||
this->defaultMutex.unlock ();
|
||||
}
|
||||
|
||||
void cac::signalRecvActivityIIU (tcpiiu &iiu)
|
||||
void cac::signalRecvActivity ()
|
||||
{
|
||||
bool change;
|
||||
|
||||
this->iiuListMutex.lock ();
|
||||
|
||||
if ( iiu.recvPending ) {
|
||||
change = false;
|
||||
}
|
||||
else {
|
||||
this->iiuListIdle.remove (iiu);
|
||||
this->iiuListRecvPending.add (iiu);
|
||||
iiu.recvPending = true;
|
||||
change = true;
|
||||
}
|
||||
|
||||
this->iiuListMutex.unlock ();
|
||||
|
||||
//
|
||||
// wakeup after unlock improves performance
|
||||
//
|
||||
if (change) {
|
||||
this->recvActivity.signal ();
|
||||
if ( this->pRecvProcThread ) {
|
||||
this->pRecvProcThread->signalActivity ();
|
||||
}
|
||||
}
|
||||
|
||||
void cac::removeIIU (tcpiiu &iiu)
|
||||
void cac::removeIIU ( tcpiiu &iiu )
|
||||
{
|
||||
this->defaultMutex.lock ();
|
||||
osiSockAddr addr = iiu.address ();
|
||||
@@ -430,12 +331,7 @@ void cac::removeIIU (tcpiiu &iiu)
|
||||
|
||||
this->iiuListMutex.lock ();
|
||||
|
||||
if ( iiu.recvPending ) {
|
||||
this->iiuListRecvPending.remove (iiu);
|
||||
}
|
||||
else {
|
||||
this->iiuListIdle.remove (iiu);
|
||||
}
|
||||
this->iiuList.remove (iiu);
|
||||
|
||||
if ( ! this->enablePreemptiveCallback ) {
|
||||
if ( this->fdRegFunc ) {
|
||||
@@ -543,6 +439,7 @@ void cac::beaconNotify ( const inetAddrID &addr )
|
||||
status = getsockname ( this->pudpiiu->getSock (), (struct sockaddr *) &saddr, &saddr_length );
|
||||
if ( status < 0 ) {
|
||||
epicsPrintf ( "CAC: getsockname () error was \"%s\"\n", SOCKERRSTR (SOCKERRNO) );
|
||||
this->defaultMutex.unlock ();
|
||||
return;
|
||||
}
|
||||
port = ntohs ( saddr.sin_port );
|
||||
@@ -560,22 +457,14 @@ void cac::beaconNotify ( const inetAddrID &addr )
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* set retry count of all disconnected channels
|
||||
* to zero
|
||||
*/
|
||||
tsDLIterBD <nciu> iter ( this->pudpiiu->chidList.first () );
|
||||
while ( iter.valid () ) {
|
||||
iter->retry = 0u;
|
||||
iter++;
|
||||
}
|
||||
|
||||
this->defaultMutex.unlock ();
|
||||
|
||||
this->pudpiiu->resetChannelRetryCounts ();
|
||||
|
||||
# if DEBUG
|
||||
{
|
||||
char buf[64];
|
||||
ipAddrToA (pnet_addr, buf, sizeof (buf) );
|
||||
ipAddrToA (pnet_addr, buf, sizeof ( buf ) );
|
||||
printf ("new server available: %s\n", buf);
|
||||
}
|
||||
# endif
|
||||
@@ -596,28 +485,53 @@ void cac::removeBeaconInetAddr (const inetAddrID &ina)
|
||||
assert (pBHE);
|
||||
}
|
||||
|
||||
void cac::decrementOutstandingIO (unsigned seqNumber)
|
||||
void cac::decrementOutstandingIO ( unsigned seqNumber )
|
||||
{
|
||||
bool signalNeeded;
|
||||
this->defaultMutex.lock ();
|
||||
if ( this->readSeq == seqNumber ) {
|
||||
if ( this->pndrecvcnt > 0u ) {
|
||||
this->pndrecvcnt--;
|
||||
if ( this->pndrecvcnt == 0u ) {
|
||||
signalNeeded = true;
|
||||
}
|
||||
else {
|
||||
signalNeeded = false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
signalNeeded = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
signalNeeded = true;
|
||||
}
|
||||
this->defaultMutex.unlock ();
|
||||
if ( this->pndrecvcnt == 0u ) {
|
||||
|
||||
if ( signalNeeded ) {
|
||||
this->ioDone.signal ();
|
||||
}
|
||||
}
|
||||
|
||||
void cac::decrementOutstandingIO ()
|
||||
{
|
||||
bool signalNeeded;
|
||||
this->defaultMutex.lock ();
|
||||
if ( this->pndrecvcnt > 0u ) {
|
||||
this->pndrecvcnt--;
|
||||
if ( this->pndrecvcnt == 0u ) {
|
||||
signalNeeded = true;
|
||||
}
|
||||
else {
|
||||
signalNeeded = false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
signalNeeded = true;
|
||||
}
|
||||
this->defaultMutex.unlock ();
|
||||
if ( this->pndrecvcnt == 0u ) {
|
||||
|
||||
if ( signalNeeded ) {
|
||||
this->ioDone.signal ();
|
||||
}
|
||||
}
|
||||
@@ -734,26 +648,150 @@ bool cac::ioComplete () const
|
||||
}
|
||||
}
|
||||
|
||||
void cac::installIO ( baseNMIU &io )
|
||||
void cac::ioInstall ( nciu &chan, baseNMIU &io )
|
||||
{
|
||||
this->defaultMutex.lock ();
|
||||
this->ioTable.add ( io );
|
||||
chan.cacPrivate::eventq.add ( io );
|
||||
this->defaultMutex.unlock ();
|
||||
}
|
||||
|
||||
void cac::uninstallIO ( baseNMIU &io )
|
||||
void cac::ioDestroy ( unsigned id )
|
||||
{
|
||||
this->defaultMutex.lock ();
|
||||
this->ioTable.remove ( io );
|
||||
baseNMIU * pmiu = this->ioTable.remove ( id );
|
||||
if ( pmiu ) {
|
||||
pmiu->chan.cacPrivate::eventq.remove ( *pmiu );
|
||||
}
|
||||
this->defaultMutex.unlock ();
|
||||
// care is taken to not destroy with the cac lock
|
||||
// applied because we could potentially hold the
|
||||
// cac lock while sending and deadlock with the
|
||||
// recv thread, but we must uninstall the IO
|
||||
// before accessing it with the lock released
|
||||
if ( pmiu ) {
|
||||
pmiu->destroy ();
|
||||
}
|
||||
}
|
||||
|
||||
baseNMIU * cac::lookupIO (unsigned id)
|
||||
void cac::ioCompletionNotify ( unsigned id )
|
||||
{
|
||||
this->defaultMutex.lock ();
|
||||
baseNMIU * pmiu = this->ioTable.lookup ( id );
|
||||
if ( pmiu ) {
|
||||
pmiu->completionNotify ();
|
||||
}
|
||||
this->defaultMutex.unlock ();
|
||||
return pmiu;
|
||||
}
|
||||
|
||||
void cac::ioCompletionNotify ( unsigned id, unsigned type,
|
||||
unsigned long count, const void *pData )
|
||||
{
|
||||
this->defaultMutex.lock ();
|
||||
baseNMIU * pmiu = this->ioTable.lookup ( id );
|
||||
if ( pmiu ) {
|
||||
pmiu->completionNotify ( type, count, pData );
|
||||
}
|
||||
this->defaultMutex.unlock ();
|
||||
}
|
||||
|
||||
void cac::ioExceptionNotify ( unsigned id, int status, const char *pContext )
|
||||
{
|
||||
this->defaultMutex.lock ();
|
||||
baseNMIU * pmiu = this->ioTable.lookup ( id );
|
||||
if ( pmiu ) {
|
||||
pmiu->exceptionNotify ( status, pContext );
|
||||
}
|
||||
this->defaultMutex.unlock ();
|
||||
}
|
||||
|
||||
void cac::ioExceptionNotify ( unsigned id, int status,
|
||||
const char *pContext, unsigned type, unsigned long count )
|
||||
{
|
||||
this->defaultMutex.lock ();
|
||||
baseNMIU * pmiu = this->ioTable.lookup ( id );
|
||||
if ( pmiu ) {
|
||||
pmiu->exceptionNotify ( status, pContext, type, count );
|
||||
}
|
||||
this->defaultMutex.unlock ();
|
||||
}
|
||||
|
||||
void cac::ioCompletionNotifyAndDestroy ( unsigned id )
|
||||
{
|
||||
this->defaultMutex.lock ();
|
||||
baseNMIU * pmiu = this->ioTable.remove ( id );
|
||||
if ( pmiu ) {
|
||||
pmiu->chan.cacPrivate::eventq.remove ( *pmiu );
|
||||
}
|
||||
this->defaultMutex.unlock ();
|
||||
// care is taken to not destroy with the cac lock
|
||||
// applied because we could potentially hold the
|
||||
// cac lock while sending and deadlock with the
|
||||
// recv thread, but we must uninstall the IO
|
||||
// before accessing it with the lock released
|
||||
if ( pmiu ) {
|
||||
pmiu->completionNotify ();
|
||||
pmiu->destroy ();
|
||||
}
|
||||
}
|
||||
|
||||
void cac::ioCompletionNotifyAndDestroy ( unsigned id,
|
||||
unsigned type, unsigned long count, const void *pData )
|
||||
{
|
||||
this->defaultMutex.lock ();
|
||||
baseNMIU * pmiu = this->ioTable.remove ( id );
|
||||
if ( pmiu ) {
|
||||
pmiu->chan.cacPrivate::eventq.remove ( *pmiu );
|
||||
}
|
||||
this->defaultMutex.unlock ();
|
||||
// care is taken to not destroy with the cac lock
|
||||
// applied because we could potentially hold the
|
||||
// cac lock while sending and deadlock with the
|
||||
// recv thread, but we must uninstall the IO
|
||||
// before accessing it with the lock released
|
||||
if ( pmiu ) {
|
||||
pmiu->completionNotify ( type, count, pData );
|
||||
pmiu->destroy ();
|
||||
}
|
||||
}
|
||||
|
||||
void cac::ioExceptionNotifyAndDestroy ( unsigned id, int status, const char *pContext )
|
||||
{
|
||||
this->defaultMutex.lock ();
|
||||
baseNMIU * pmiu = this->ioTable.remove ( id );
|
||||
if ( pmiu ) {
|
||||
pmiu->chan.cacPrivate::eventq.remove ( *pmiu );
|
||||
}
|
||||
this->defaultMutex.unlock ();
|
||||
// care is taken to not destroy with the cac lock
|
||||
// applied because we could potentially hold the
|
||||
// cac lock while sending and deadlock with the
|
||||
// recv thread, but we must uninstall the IO
|
||||
// before accessing it with the lock released
|
||||
if ( pmiu ) {
|
||||
pmiu->exceptionNotify ( status, pContext );
|
||||
pmiu->destroy ();
|
||||
}
|
||||
}
|
||||
|
||||
void cac::ioExceptionNotifyAndDestroy ( unsigned id, int status,
|
||||
const char *pContext, unsigned type, unsigned long count )
|
||||
{
|
||||
this->defaultMutex.lock ();
|
||||
baseNMIU * pmiu = this->ioTable.remove ( id );
|
||||
if ( pmiu ) {
|
||||
pmiu->chan.cacPrivate::eventq.remove ( *pmiu );
|
||||
}
|
||||
this->defaultMutex.unlock ();
|
||||
// care is taken to not destroy with the cac lock
|
||||
// applied because we could potentially hold the
|
||||
// cac lock while sending and deadlock with the
|
||||
// recv thread, but we must uninstall the IO
|
||||
// before accessing it with the lock released
|
||||
if ( pmiu ) {
|
||||
pmiu->exceptionNotify ( status, pContext, type, count );
|
||||
pmiu->destroy ();
|
||||
}
|
||||
}
|
||||
|
||||
void cac::registerChannel (nciu &chan)
|
||||
@@ -763,19 +801,59 @@ void cac::registerChannel (nciu &chan)
|
||||
this->defaultMutex.unlock ();
|
||||
}
|
||||
|
||||
void cac::unregisterChannel (nciu &chan)
|
||||
void cac::unregisterChannel ( nciu &chan )
|
||||
{
|
||||
this->defaultMutex.lock ();
|
||||
this->chanTable.remove ( chan );
|
||||
this->defaultMutex.unlock ();
|
||||
}
|
||||
|
||||
nciu * cac::lookupChan (unsigned id)
|
||||
void cac::accessRightsNotify ( unsigned id, caar ar )
|
||||
{
|
||||
this->defaultMutex.lock ();
|
||||
nciu * pchan = this->chanTable.lookup ( id );
|
||||
nciu * pChan = this->chanTable.lookup ( id );
|
||||
if ( pChan ) {
|
||||
pChan->accessRightsStateChange ( ar );
|
||||
}
|
||||
this->defaultMutex.unlock ();
|
||||
}
|
||||
|
||||
void cac::connectChannel ( unsigned id, class tcpiiu &iiu,
|
||||
unsigned nativeType, unsigned long nativeCount, unsigned sid )
|
||||
{
|
||||
this->defaultMutex.lock ();
|
||||
nciu * pChan = this->chanTable.lookup ( id );
|
||||
if ( pChan ) {
|
||||
unsigned sidTmp;
|
||||
if ( iiu.ca_v44_ok () ) {
|
||||
sidTmp = sid;
|
||||
}
|
||||
else {
|
||||
sidTmp = pChan->getSID ();
|
||||
}
|
||||
pChan->connect ( iiu, nativeType, nativeCount, sidTmp );
|
||||
}
|
||||
this->defaultMutex.unlock ();
|
||||
}
|
||||
|
||||
void cac::channelDestroy ( unsigned id )
|
||||
{
|
||||
this->defaultMutex.lock ();
|
||||
nciu * pChan = this->chanTable.lookup ( id );
|
||||
if ( pChan ) {
|
||||
pChan->destroy ();
|
||||
}
|
||||
this->defaultMutex.unlock ();
|
||||
}
|
||||
|
||||
void cac::disconnectChannel ( unsigned id )
|
||||
{
|
||||
this->defaultMutex.lock ();
|
||||
nciu * pChan = this->chanTable.lookup ( id );
|
||||
if ( pChan ) {
|
||||
pChan->disconnect ();
|
||||
}
|
||||
this->defaultMutex.unlock ();
|
||||
return pchan;
|
||||
}
|
||||
|
||||
void cac::installCASG (CASG &sg)
|
||||
@@ -837,7 +915,7 @@ bool cac::createChannelIO (const char *pName, cacChannel &chan)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
nciu *pNetChan = new nciu ( this, chan, pName );
|
||||
nciu *pNetChan = new nciu ( *this, chan, pName );
|
||||
if ( pNetChan ) {
|
||||
if ( ! pNetChan->fullyConstructed () ) {
|
||||
pNetChan->destroy ();
|
||||
@@ -867,7 +945,7 @@ bool cac::setupUDP ()
|
||||
return true;
|
||||
}
|
||||
|
||||
this->pudpiiu = new udpiiu ( this );
|
||||
this->pudpiiu = new udpiiu ( *this );
|
||||
if ( ! this->pudpiiu ) {
|
||||
this->defaultMutex.unlock ();
|
||||
return false;
|
||||
@@ -877,6 +955,7 @@ bool cac::setupUDP ()
|
||||
if ( ! this->pSearchTmr ) {
|
||||
delete this->pudpiiu;
|
||||
this->pudpiiu = 0;
|
||||
this->defaultMutex.unlock ();
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -901,16 +980,6 @@ bool cac::setupUDP ()
|
||||
return true;
|
||||
}
|
||||
|
||||
void cac::lock () const
|
||||
{
|
||||
this->defaultMutex.lock ();
|
||||
}
|
||||
|
||||
void cac::unlock () const
|
||||
{
|
||||
this->defaultMutex.unlock ();
|
||||
}
|
||||
|
||||
void cac::registerForFileDescriptorCallBack ( CAFDHANDLER *pFunc, void *pArg )
|
||||
{
|
||||
this->defaultMutex.lock ();
|
||||
@@ -921,12 +990,16 @@ void cac::registerForFileDescriptorCallBack ( CAFDHANDLER *pFunc, void *pArg )
|
||||
|
||||
void cac::enableCallbackPreemption ()
|
||||
{
|
||||
this->pProcThread->enable ();
|
||||
if ( this->pRecvProcThread ) {
|
||||
this->pRecvProcThread->enable ();
|
||||
}
|
||||
}
|
||||
|
||||
void cac::disableCallbackPreemption ()
|
||||
{
|
||||
this->pProcThread->disable ();
|
||||
if ( this->pRecvProcThread ) {
|
||||
this->pRecvProcThread->disable ();
|
||||
}
|
||||
}
|
||||
|
||||
void cac::changeExceptionEvent ( caExceptionHandler *pfunc, void *arg )
|
||||
@@ -980,10 +1053,9 @@ void cac::installDisconnectedChannel ( nciu &chan )
|
||||
|
||||
assert ( this->pudpiiu && this->pSearchTmr );
|
||||
|
||||
this->defaultMutex.lock ();
|
||||
this->pudpiiu->addToChanList ( chan );
|
||||
chan.attachChanToIIU ( *this->pudpiiu );
|
||||
chan.resetRetryCount ();
|
||||
this->pSearchTmr->reset ( CA_RECAST_DELAY );
|
||||
this->defaultMutex.unlock ();
|
||||
}
|
||||
|
||||
void cac::notifySearchResponse ( unsigned short retrySeqNo )
|
||||
@@ -1004,10 +1076,123 @@ void cac::replaceErrLogHandler ( caPrintfFunc *ca_printf_func )
|
||||
{
|
||||
this->defaultMutex.lock ();
|
||||
if ( ca_printf_func ) {
|
||||
this->ca_printf_func = ca_printf_func;
|
||||
this->pVPrintfFunc = ca_printf_func;
|
||||
}
|
||||
else {
|
||||
this->ca_printf_func = epicsVprintf;
|
||||
this->pVPrintfFunc = epicsVprintf;
|
||||
}
|
||||
this->defaultMutex.unlock ();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* constructTCPIIU ()
|
||||
*/
|
||||
tcpiiu * cac::constructTCPIIU ( const osiSockAddr &addr, unsigned minorVersion )
|
||||
{
|
||||
bhe *pBHE;
|
||||
tcpiiu *piiu;
|
||||
|
||||
if ( addr.sa.sa_family != AF_INET ) {
|
||||
return 0u;
|
||||
}
|
||||
|
||||
/*
|
||||
* look for an existing virtual circuit
|
||||
*/
|
||||
this->defaultMutex.lock ();
|
||||
pBHE = this->lookupBeaconInetAddr ( addr.ia );
|
||||
if ( ! pBHE ) {
|
||||
pBHE = this->createBeaconHashEntry ( addr.ia, osiTime () );
|
||||
if ( ! pBHE ) {
|
||||
this->defaultMutex.unlock ();
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
piiu = pBHE->getIIU ();
|
||||
if ( piiu ) {
|
||||
if ( piiu->alive () ) {
|
||||
this->defaultMutex.unlock ();
|
||||
return piiu;
|
||||
}
|
||||
else {
|
||||
this->defaultMutex.unlock ();
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
this->defaultMutex.unlock ();
|
||||
|
||||
piiu = new tcpiiu ( *this, addr, minorVersion,
|
||||
*pBHE, this->connTMO, *this->pTimerQueue,
|
||||
this->ipToAEngine );
|
||||
if ( ! piiu ) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ( piiu->fullyConstructed () ) {
|
||||
return piiu;
|
||||
}
|
||||
else {
|
||||
delete piiu;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void cac::lookupChannelAndTransferToTCP ( unsigned cid, unsigned sid,
|
||||
unsigned typeCode, unsigned long count,
|
||||
unsigned minorVersionNumber, const osiSockAddr &addr )
|
||||
{
|
||||
unsigned retrySeqNumber;
|
||||
tcpiiu *allocpiiu;
|
||||
|
||||
{
|
||||
this->defaultMutex.lock ();
|
||||
nciu *chan;
|
||||
|
||||
/*
|
||||
* ignore search replies for deleted channels
|
||||
*/
|
||||
chan = this->chanTable.lookup ( cid );
|
||||
if ( ! chan ) {
|
||||
this->defaultMutex.unlock ();
|
||||
return;
|
||||
}
|
||||
|
||||
retrySeqNumber = chan->getRetrySeqNo ();
|
||||
|
||||
/*
|
||||
* Ignore duplicate search replies
|
||||
*/
|
||||
if ( chan->connectionInProgress ( addr ) ) {
|
||||
this->defaultMutex.unlock ();
|
||||
return;
|
||||
}
|
||||
|
||||
allocpiiu = this->constructTCPIIU ( addr, minorVersionNumber );
|
||||
if ( ! allocpiiu ) {
|
||||
this->defaultMutex.unlock ();
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* remove it from the broadcast niiu
|
||||
*/
|
||||
chan->searchReplySetUp ( sid, typeCode, count );
|
||||
allocpiiu->installChannelPendingClaim ( *chan );
|
||||
|
||||
this->defaultMutex.unlock ();
|
||||
}
|
||||
|
||||
this->notifySearchResponse ( retrySeqNumber );
|
||||
return;
|
||||
}
|
||||
|
||||
bool cac::currentThreadIsRecvProcessThread ()
|
||||
{
|
||||
if ( this->pRecvProcThread ) {
|
||||
return this->pRecvProcThread->isCurrentThread ();
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
+70
-47
@@ -23,8 +23,9 @@ cacChannel::cacChannel () : pChannelIO (0)
|
||||
|
||||
cacChannel::~cacChannel ()
|
||||
{
|
||||
if ( this->pChannelIO ) {
|
||||
this->pChannelIO->destroy ();
|
||||
cacChannelIO *pIO = this->pChannelIO;
|
||||
if ( pIO ) {
|
||||
pIO->destroy ();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,8 +38,9 @@ void cacChannel::attachIO (cacChannelIO &io)
|
||||
|
||||
int cacChannel::read ( unsigned type, unsigned long count, cacNotify & notify )
|
||||
{
|
||||
if ( this->pChannelIO ) {
|
||||
return pChannelIO->read (type, count, notify);
|
||||
cacChannelIO *pIO = this->pChannelIO;
|
||||
if ( pIO ) {
|
||||
return pIO->read ( type, count, notify );
|
||||
}
|
||||
else {
|
||||
return ECA_DISCONNCHID;
|
||||
@@ -47,8 +49,9 @@ int cacChannel::read ( unsigned type, unsigned long count, cacNotify & notify )
|
||||
|
||||
int cacChannel::read ( unsigned type, unsigned long count, void *pValue )
|
||||
{
|
||||
if ( this->pChannelIO ) {
|
||||
return pChannelIO->read (type, count, pValue);
|
||||
cacChannelIO *pIO = this->pChannelIO;
|
||||
if ( pIO ) {
|
||||
return pIO->read ( type, count, pValue );
|
||||
}
|
||||
else {
|
||||
return ECA_DISCONNCHID;
|
||||
@@ -57,8 +60,9 @@ int cacChannel::read ( unsigned type, unsigned long count, void *pValue )
|
||||
|
||||
int cacChannel::write (unsigned type, unsigned long count, const void *pvalue )
|
||||
{
|
||||
if ( this->pChannelIO ) {
|
||||
return pChannelIO->write (type, count, pvalue);
|
||||
cacChannelIO *pIO = this->pChannelIO;
|
||||
if ( pIO ) {
|
||||
return pIO->write (type, count, pvalue);
|
||||
}
|
||||
else {
|
||||
return ECA_DISCONNCHID;
|
||||
@@ -68,8 +72,9 @@ int cacChannel::write (unsigned type, unsigned long count, const void *pvalue )
|
||||
int cacChannel::write (unsigned type, unsigned long count,
|
||||
const void *pvalue, cacNotify & notify )
|
||||
{
|
||||
if ( this->pChannelIO ) {
|
||||
return pChannelIO->write (type, count, pvalue, notify);
|
||||
cacChannelIO *pIO = this->pChannelIO;
|
||||
if ( pIO ) {
|
||||
return pIO->write (type, count, pvalue, notify);
|
||||
}
|
||||
else {
|
||||
return ECA_DISCONNCHID;
|
||||
@@ -79,8 +84,9 @@ int cacChannel::write (unsigned type, unsigned long count,
|
||||
int cacChannel::subscribe ( unsigned type, unsigned long count,
|
||||
unsigned mask, cacNotify ¬ify )
|
||||
{
|
||||
if ( this->pChannelIO ) {
|
||||
return pChannelIO->subscribe (type, count, mask, notify);
|
||||
cacChannelIO *pIO = this->pChannelIO;
|
||||
if ( pIO ) {
|
||||
return pIO->subscribe (type, count, mask, notify);
|
||||
}
|
||||
else {
|
||||
return ECA_DISCONNCHID;
|
||||
@@ -90,8 +96,9 @@ int cacChannel::subscribe ( unsigned type, unsigned long count,
|
||||
void cacChannel::hostName ( char *pBuf, unsigned bufLength ) const
|
||||
{
|
||||
if ( bufLength ) {
|
||||
if ( this->pChannelIO ) {
|
||||
pChannelIO->hostName (pBuf, bufLength);
|
||||
cacChannelIO *pIO = this->pChannelIO;
|
||||
if ( pIO ) {
|
||||
pIO->hostName (pBuf, bufLength);
|
||||
}
|
||||
else {
|
||||
strncpy ( pBuf, "<not connected>", bufLength );
|
||||
@@ -102,8 +109,9 @@ void cacChannel::hostName ( char *pBuf, unsigned bufLength ) const
|
||||
|
||||
const char * cacChannel::pHostName () const
|
||||
{
|
||||
if ( this->pChannelIO ) {
|
||||
return pChannelIO->pHostName ();
|
||||
cacChannelIO *pIO = this->pChannelIO;
|
||||
if ( pIO ) {
|
||||
return pIO->pHostName ();
|
||||
}
|
||||
else {
|
||||
return "<not connected>";
|
||||
@@ -112,8 +120,9 @@ const char * cacChannel::pHostName () const
|
||||
|
||||
short cacChannel::nativeType () const
|
||||
{
|
||||
if ( this->pChannelIO ) {
|
||||
return pChannelIO->nativeType ();
|
||||
cacChannelIO *pIO = this->pChannelIO;
|
||||
if ( pIO ) {
|
||||
return pIO->nativeType ();
|
||||
}
|
||||
else {
|
||||
return TYPENOTCONN;
|
||||
@@ -122,8 +131,9 @@ short cacChannel::nativeType () const
|
||||
|
||||
unsigned long cacChannel::nativeElementCount () const
|
||||
{
|
||||
if ( this->pChannelIO ) {
|
||||
return pChannelIO->nativeElementCount ();
|
||||
cacChannelIO *pIO = this->pChannelIO;
|
||||
if ( pIO ) {
|
||||
return pIO->nativeElementCount ();
|
||||
}
|
||||
else {
|
||||
return 0ul;
|
||||
@@ -132,8 +142,9 @@ unsigned long cacChannel::nativeElementCount () const
|
||||
|
||||
channel_state cacChannel::state () const
|
||||
{
|
||||
if ( this->pChannelIO ) {
|
||||
return pChannelIO->state ();
|
||||
cacChannelIO *pIO = this->pChannelIO;
|
||||
if ( pIO ) {
|
||||
return pIO->state ();
|
||||
}
|
||||
else {
|
||||
return cs_never_conn;
|
||||
@@ -142,8 +153,9 @@ channel_state cacChannel::state () const
|
||||
|
||||
bool cacChannel::readAccess () const
|
||||
{
|
||||
if ( this->pChannelIO ) {
|
||||
caar ar = pChannelIO->accessRights ();
|
||||
cacChannelIO *pIO = this->pChannelIO;
|
||||
if ( pIO ) {
|
||||
caar ar = pIO->accessRights ();
|
||||
return ar.read_access;
|
||||
}
|
||||
else {
|
||||
@@ -153,7 +165,8 @@ bool cacChannel::readAccess () const
|
||||
|
||||
bool cacChannel::writeAccess () const
|
||||
{
|
||||
if ( this->pChannelIO ) {
|
||||
cacChannelIO *pIO = this->pChannelIO;
|
||||
if ( pIO ) {
|
||||
caar ar = pChannelIO->accessRights ();
|
||||
return ar.write_access;
|
||||
}
|
||||
@@ -164,8 +177,9 @@ bool cacChannel::writeAccess () const
|
||||
|
||||
const char *cacChannel::pName () const
|
||||
{
|
||||
if ( this->pChannelIO ) {
|
||||
return pChannelIO->pName ();
|
||||
cacChannelIO *pIO = this->pChannelIO;
|
||||
if ( pIO ) {
|
||||
return pIO->pName ();
|
||||
}
|
||||
else {
|
||||
return "<disconnected>";
|
||||
@@ -174,8 +188,9 @@ const char *cacChannel::pName () const
|
||||
|
||||
unsigned cacChannel::searchAttempts () const
|
||||
{
|
||||
if ( this->pChannelIO ) {
|
||||
return pChannelIO->searchAttempts ();
|
||||
cacChannelIO *pIO = this->pChannelIO;
|
||||
if ( pIO ) {
|
||||
return pIO->searchAttempts ();
|
||||
}
|
||||
else {
|
||||
return 0u;
|
||||
@@ -184,8 +199,9 @@ unsigned cacChannel::searchAttempts () const
|
||||
|
||||
bool cacChannel::ca_v42_ok () const
|
||||
{
|
||||
if ( this->pChannelIO ) {
|
||||
return pChannelIO->ca_v42_ok ();
|
||||
cacChannelIO *pIO = this->pChannelIO;
|
||||
if ( pIO ) {
|
||||
return pIO->ca_v42_ok ();
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
@@ -194,8 +210,9 @@ bool cacChannel::ca_v42_ok () const
|
||||
|
||||
bool cacChannel::connected () const
|
||||
{
|
||||
if ( this->pChannelIO ) {
|
||||
return pChannelIO->connected ();
|
||||
cacChannelIO *pIO = this->pChannelIO;
|
||||
if ( pIO ) {
|
||||
return pIO->connected ();
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
@@ -204,8 +221,9 @@ bool cacChannel::connected () const
|
||||
|
||||
caar cacChannel::accessRights () const
|
||||
{
|
||||
if ( this->pChannelIO ) {
|
||||
return pChannelIO->accessRights ();
|
||||
cacChannelIO *pIO = this->pChannelIO;
|
||||
if ( pIO ) {
|
||||
return pIO->accessRights ();
|
||||
}
|
||||
else {
|
||||
caar ar;
|
||||
@@ -246,8 +264,9 @@ void cacChannel::connectTimeoutNotify ()
|
||||
|
||||
unsigned cacChannel::readSequence () const
|
||||
{
|
||||
if ( this->pChannelIO ) {
|
||||
return this->pChannelIO->readSequence ();
|
||||
cacChannelIO *pIO = this->pChannelIO;
|
||||
if ( pIO ) {
|
||||
return pIO->readSequence ();
|
||||
}
|
||||
else {
|
||||
return 0u;
|
||||
@@ -256,28 +275,32 @@ unsigned cacChannel::readSequence () const
|
||||
|
||||
void cacChannel::decrementOutstandingIO ()
|
||||
{
|
||||
if ( this->pChannelIO ) {
|
||||
this->pChannelIO->decrementOutstandingIO ();
|
||||
cacChannelIO *pIO = this->pChannelIO;
|
||||
if ( pIO ) {
|
||||
pIO->decrementOutstandingIO ();
|
||||
}
|
||||
}
|
||||
|
||||
void cacChannel::incrementOutstandingIO ()
|
||||
{
|
||||
if ( this->pChannelIO ) {
|
||||
this->pChannelIO->incrementOutstandingIO ();
|
||||
cacChannelIO *pIO = this->pChannelIO;
|
||||
if ( pIO ) {
|
||||
pIO->incrementOutstandingIO ();
|
||||
}
|
||||
}
|
||||
|
||||
void cacChannel::lock () const
|
||||
void cacChannel::lockOutstandingIO () const
|
||||
{
|
||||
if ( this->pChannelIO ) {
|
||||
this->pChannelIO->lock ();
|
||||
cacChannelIO *pIO = this->pChannelIO;
|
||||
if ( pIO ) {
|
||||
pIO->lockOutstandingIO ();
|
||||
}
|
||||
}
|
||||
|
||||
void cacChannel::unlock () const
|
||||
void cacChannel::unlockOutstandingIO () const
|
||||
{
|
||||
if ( this->pChannelIO ) {
|
||||
this->pChannelIO->unlock ();
|
||||
cacChannelIO *pIO = this->pChannelIO;
|
||||
if ( pIO ) {
|
||||
pIO->unlockOutstandingIO ();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,4 +107,12 @@ void cacChannelIO::decrementOutstandingIO ()
|
||||
{
|
||||
}
|
||||
|
||||
void cacChannelIO::lockOutstandingIO () const
|
||||
{
|
||||
}
|
||||
|
||||
void cacChannelIO::unlockOutstandingIO () const
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
+7
-7
@@ -86,8 +86,8 @@ public:
|
||||
protected:
|
||||
class cacChannelIO *pChannelIO;
|
||||
|
||||
void lock () const;
|
||||
void unlock () const;
|
||||
void lockOutstandingIO () const;
|
||||
void unlockOutstandingIO () const;
|
||||
|
||||
private:
|
||||
virtual void ioAttachNotify ();
|
||||
@@ -116,8 +116,8 @@ public:
|
||||
|
||||
virtual const char *pName () const = 0;
|
||||
|
||||
virtual void lock () const = 0;
|
||||
virtual void unlock () const = 0;
|
||||
virtual void lockOutstandingIO () const = 0;
|
||||
virtual void unlockOutstandingIO () const = 0;
|
||||
|
||||
private:
|
||||
virtual int read ( unsigned type, unsigned long count, void *pValue) = 0;
|
||||
@@ -143,11 +143,11 @@ private:
|
||||
friend class cacChannel;
|
||||
};
|
||||
|
||||
class epicsShareClass cacLocalChannelIO :
|
||||
class cacLocalChannelIO :
|
||||
public cacChannelIO, public tsDLNode <cacLocalChannelIO> {
|
||||
public:
|
||||
cacLocalChannelIO ( cacChannel &chan );
|
||||
virtual ~cacLocalChannelIO () = 0;
|
||||
epicsShareFunc cacLocalChannelIO ( cacChannel &chan );
|
||||
epicsShareFunc virtual ~cacLocalChannelIO () = 0;
|
||||
};
|
||||
|
||||
struct cacServiceIO : public tsDLNode <cacServiceIO> {
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
*
|
||||
* L O S A L A M O S
|
||||
* Los Alamos National Laboratory
|
||||
* Los Alamos, New Mexico 87545
|
||||
*
|
||||
* Copyright, 1986, The Regents of the University of California.
|
||||
*
|
||||
*
|
||||
* Author Jeffrey O. Hill
|
||||
* johill@lanl.gov
|
||||
* 505 665 1831
|
||||
*/
|
||||
|
||||
#include "iocinf.h"
|
||||
|
||||
cacPrivate::cacPrivate ( cac &cacIn ) :
|
||||
cacCtx ( cacIn )
|
||||
{
|
||||
}
|
||||
|
||||
// Destroy all IO blocks attached.
|
||||
// Care is taken here not to hold the lock while
|
||||
// sending a subscription delete message (which
|
||||
// would result in deadlocks)
|
||||
void cacPrivate::destroyAllIO ()
|
||||
{
|
||||
while ( true ) {
|
||||
unsigned id;
|
||||
bool done;
|
||||
|
||||
this->cacCtx.defaultMutex.lock ();
|
||||
{
|
||||
baseNMIU *pNMIU = this->eventq.first ();
|
||||
if ( pNMIU ) {
|
||||
id = pNMIU->getId ();
|
||||
done = false;
|
||||
}
|
||||
else {
|
||||
done = true;
|
||||
}
|
||||
}
|
||||
this->cacCtx.defaultMutex.unlock ();
|
||||
|
||||
if ( done ) {
|
||||
break;
|
||||
}
|
||||
// care is taken to not hold a lock when
|
||||
// executing this
|
||||
this->cacCtx.ioDestroy ( id );
|
||||
}
|
||||
}
|
||||
|
||||
// resubscribe for monitors from this channel
|
||||
void cacPrivate::subscribeAllIO ()
|
||||
{
|
||||
this->cacCtx.defaultMutex.lock ();
|
||||
tsDLIterBD < baseNMIU > iter = this->eventq.first ();
|
||||
while ( iter.valid () ) {
|
||||
iter->subscriptionMsg ();
|
||||
iter++;
|
||||
}
|
||||
this->cacCtx.defaultMutex.unlock ();
|
||||
}
|
||||
|
||||
// cancel IO operations and monitor subscriptions
|
||||
void cacPrivate::disconnectAllIO ( const char *pHostName )
|
||||
{
|
||||
this->cacCtx.defaultMutex.lock ();
|
||||
tsDLIterBD < baseNMIU > iter = this->eventq.first ();
|
||||
while ( iter.valid () ) {
|
||||
tsDLIterBD < baseNMIU > next = iter.itemAfter ();
|
||||
iter->disconnect ( pHostName );
|
||||
iter = next;
|
||||
}
|
||||
this->cacCtx.defaultMutex.unlock ();
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
*
|
||||
* L O S A L A M O S
|
||||
* Los Alamos National Laboratory
|
||||
* Los Alamos, New Mexico 87545
|
||||
*
|
||||
* Copyright, 1986, The Regents of the University of California.
|
||||
*
|
||||
*
|
||||
* Author Jeffrey O. Hill
|
||||
* johill@lanl.gov
|
||||
* 505 665 1831
|
||||
*/
|
||||
|
||||
inline int cac::vPrintf ( const char *pformat, va_list args )
|
||||
{
|
||||
return ( *this->pVPrintfFunc ) ( pformat, args );
|
||||
}
|
||||
|
||||
inline int cac::printf ( const char *pformat, ... )
|
||||
{
|
||||
va_list theArgs;
|
||||
int status;
|
||||
|
||||
va_start ( theArgs, pformat );
|
||||
|
||||
status = this->vPrintf ( pformat, theArgs );
|
||||
|
||||
va_end ( theArgs );
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
inline double cac::connectionTimeout () const
|
||||
{
|
||||
return this->connTMO;
|
||||
}
|
||||
|
||||
inline const char * cac::userNamePointer ()
|
||||
{
|
||||
return this->pUserName;
|
||||
}
|
||||
|
||||
inline void cac::lockOutstandingIO () const
|
||||
{
|
||||
this->defaultMutex.lock ();
|
||||
}
|
||||
|
||||
inline void cac::unlockOutstandingIO () const
|
||||
{
|
||||
this->defaultMutex.unlock ();
|
||||
}
|
||||
+2
-1
@@ -37,7 +37,6 @@
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include "ellLib.h"
|
||||
#include "osiThread.h"
|
||||
#include "shareLib.h"
|
||||
#include "caerr.h"
|
||||
@@ -719,6 +718,8 @@ epicsShareFunc void epicsShareAPI ca_signal_formated (long ca_status, const char
|
||||
* ca_host_name_function()
|
||||
*
|
||||
* channel R channel identifier
|
||||
*
|
||||
* !!!! this function is _not_ thread safe !!!!
|
||||
*/
|
||||
epicsShareFunc const char * epicsShareAPI ca_host_name (chid channel);
|
||||
/* thread safe version */
|
||||
|
||||
+38
-40
@@ -28,7 +28,7 @@
|
||||
|
||||
#define CA_M_MSG_NO 0x0000FFF8
|
||||
#define CA_M_SEVERITY 0x00000007
|
||||
#define CA_M_LEVEL 0x00000003
|
||||
#define CA_M_LEVEL 0x00000003
|
||||
#define CA_M_SUCCESS 0x00000001
|
||||
#define CA_M_ERROR 0x00000002
|
||||
#define CA_M_SEVERE 0x00000004
|
||||
@@ -62,42 +62,42 @@
|
||||
|
||||
|
||||
#define ECA_NORMAL DEFMSG(CA_K_SUCCESS, 0)
|
||||
#define ECA_MAXIOC DEFMSG(CA_K_ERROR, 1)
|
||||
#define ECA_UKNHOST DEFMSG(CA_K_ERROR, 2)
|
||||
#define ECA_UKNSERV DEFMSG(CA_K_ERROR, 3)
|
||||
#define ECA_SOCK DEFMSG(CA_K_ERROR, 4)
|
||||
#define ECA_MAXIOC DEFMSG(CA_K_ERROR, 1)
|
||||
#define ECA_UKNHOST DEFMSG(CA_K_ERROR, 2)
|
||||
#define ECA_UKNSERV DEFMSG(CA_K_ERROR, 3)
|
||||
#define ECA_SOCK DEFMSG(CA_K_ERROR, 4)
|
||||
#define ECA_CONN DEFMSG(CA_K_WARNING, 5)
|
||||
#define ECA_ALLOCMEM DEFMSG(CA_K_WARNING, 6)
|
||||
#define ECA_UKNCHAN DEFMSG(CA_K_WARNING, 7)
|
||||
#define ECA_UKNFIELD DEFMSG(CA_K_WARNING, 8)
|
||||
#define ECA_TOLARGE DEFMSG(CA_K_ERROR, 9)
|
||||
#define ECA_TIMEOUT DEFMSG(CA_K_WARNING, 10)
|
||||
#define ECA_NOSUPPORT DEFMSG(CA_K_WARNING, 11)
|
||||
#define ECA_STRTOBIG DEFMSG(CA_K_WARNING, 12)
|
||||
#define ECA_DISCONNCHID DEFMSG(CA_K_ERROR, 13)
|
||||
#define ECA_BADTYPE DEFMSG(CA_K_ERROR, 14)
|
||||
#define ECA_CHIDNOTFND DEFMSG(CA_K_INFO, 15)
|
||||
#define ECA_CHIDRETRY DEFMSG(CA_K_INFO, 16)
|
||||
#define ECA_INTERNAL DEFMSG(CA_K_FATAL, 17)
|
||||
#define ECA_DBLCLFAIL DEFMSG(CA_K_WARNING, 18)
|
||||
#define ECA_GETFAIL DEFMSG(CA_K_WARNING, 19)
|
||||
#define ECA_PUTFAIL DEFMSG(CA_K_WARNING, 20)
|
||||
#define ECA_ADDFAIL DEFMSG(CA_K_WARNING, 21)
|
||||
#define ECA_BADCOUNT DEFMSG(CA_K_WARNING, 22)
|
||||
#define ECA_BADSTR DEFMSG(CA_K_ERROR, 23)
|
||||
#define ECA_DISCONN DEFMSG(CA_K_WARNING, 24)
|
||||
#define ECA_DBLCHNL DEFMSG(CA_K_WARNING, 25)
|
||||
#define ECA_EVDISALLOW DEFMSG(CA_K_ERROR, 26)
|
||||
#define ECA_BUILDGET DEFMSG(CA_K_WARNING, 27)
|
||||
#define ECA_NEEDSFP DEFMSG(CA_K_WARNING, 28)
|
||||
#define ECA_OVEVFAIL DEFMSG(CA_K_WARNING, 29)
|
||||
#define ECA_BADMONID DEFMSG(CA_K_ERROR, 30)
|
||||
#define ECA_NEWADDR DEFMSG(CA_K_WARNING, 31)
|
||||
#define ECA_NEWCONN DEFMSG(CA_K_INFO, 32)
|
||||
#define ECA_NOCACTX DEFMSG(CA_K_WARNING, 33)
|
||||
#define ECA_DEFUNCT DEFMSG(CA_K_FATAL, 34)
|
||||
#define ECA_EMPTYSTR DEFMSG(CA_K_WARNING, 35)
|
||||
#define ECA_NOREPEATER DEFMSG(CA_K_WARNING, 36)
|
||||
#define ECA_TOLARGE DEFMSG(CA_K_ERROR, 9)
|
||||
#define ECA_TIMEOUT DEFMSG(CA_K_WARNING, 10)
|
||||
#define ECA_NOSUPPORT DEFMSG(CA_K_WARNING, 11)
|
||||
#define ECA_STRTOBIG DEFMSG(CA_K_WARNING, 12)
|
||||
#define ECA_DISCONNCHID DEFMSG(CA_K_ERROR, 13)
|
||||
#define ECA_BADTYPE DEFMSG(CA_K_ERROR, 14)
|
||||
#define ECA_CHIDNOTFND DEFMSG(CA_K_INFO, 15)
|
||||
#define ECA_CHIDRETRY DEFMSG(CA_K_INFO, 16)
|
||||
#define ECA_INTERNAL DEFMSG(CA_K_FATAL, 17)
|
||||
#define ECA_DBLCLFAIL DEFMSG(CA_K_WARNING, 18)
|
||||
#define ECA_GETFAIL DEFMSG(CA_K_WARNING, 19)
|
||||
#define ECA_PUTFAIL DEFMSG(CA_K_WARNING, 20)
|
||||
#define ECA_ADDFAIL DEFMSG(CA_K_WARNING, 21)
|
||||
#define ECA_BADCOUNT DEFMSG(CA_K_WARNING, 22)
|
||||
#define ECA_BADSTR DEFMSG(CA_K_ERROR, 23)
|
||||
#define ECA_DISCONN DEFMSG(CA_K_WARNING, 24)
|
||||
#define ECA_DBLCHNL DEFMSG(CA_K_WARNING, 25)
|
||||
#define ECA_EVDISALLOW DEFMSG(CA_K_ERROR, 26)
|
||||
#define ECA_BUILDGET DEFMSG(CA_K_WARNING, 27)
|
||||
#define ECA_NEEDSFP DEFMSG(CA_K_WARNING, 28)
|
||||
#define ECA_OVEVFAIL DEFMSG(CA_K_WARNING, 29)
|
||||
#define ECA_BADMONID DEFMSG(CA_K_ERROR, 30)
|
||||
#define ECA_NEWADDR DEFMSG(CA_K_WARNING, 31)
|
||||
#define ECA_NEWCONN DEFMSG(CA_K_INFO, 32)
|
||||
#define ECA_NOCACTX DEFMSG(CA_K_WARNING, 33)
|
||||
#define ECA_DEFUNCT DEFMSG(CA_K_FATAL, 34)
|
||||
#define ECA_EMPTYSTR DEFMSG(CA_K_WARNING, 35)
|
||||
#define ECA_NOREPEATER DEFMSG(CA_K_WARNING, 36)
|
||||
#define ECA_NOCHANMSG DEFMSG(CA_K_WARNING, 37)
|
||||
#define ECA_DLCKREST DEFMSG(CA_K_WARNING, 38)
|
||||
#define ECA_SERVBEHIND DEFMSG(CA_K_WARNING, 39)
|
||||
@@ -109,13 +109,12 @@
|
||||
#define ECA_PUTCBINPROG DEFMSG(CA_K_ERROR, 45)
|
||||
#define ECA_NORDACCESS DEFMSG(CA_K_WARNING, 46)
|
||||
#define ECA_NOWTACCESS DEFMSG(CA_K_WARNING, 47)
|
||||
#define ECA_ANACHRONISM DEFMSG(CA_K_ERROR, 48)
|
||||
#define ECA_ANACHRONISM DEFMSG(CA_K_ERROR, 48)
|
||||
#define ECA_NOSEARCHADDR DEFMSG(CA_K_WARNING, 49)
|
||||
#define ECA_NOCONVERT DEFMSG(CA_K_WARNING, 50)
|
||||
#define ECA_BADCHID DEFMSG(CA_K_ERROR, 51)
|
||||
#define ECA_BADFUNCPTR DEFMSG(CA_K_ERROR, 52)
|
||||
#define ECA_OPWILLBLOCK DEFMSG(CA_K_WARNING, 53)
|
||||
#define ECA_ISATTACHED DEFMSG(CA_K_WARNING, 54)
|
||||
#define ECA_BADCHID DEFMSG(CA_K_ERROR, 51)
|
||||
#define ECA_BADFUNCPTR DEFMSG(CA_K_ERROR, 52)
|
||||
#define ECA_ISATTACHED DEFMSG(CA_K_WARNING, 53)
|
||||
|
||||
#ifndef CA_ERROR_GLBLSOURCE
|
||||
epicsShareExtern READONLY char *ca_message_text[];
|
||||
@@ -148,7 +147,7 @@ READONLY char *ca_message_text[]
|
||||
"Count requested inappropriate for that channel",
|
||||
"The supplied string has improper format",
|
||||
"Network connection lost",
|
||||
"Ambiguous channel host (multiple IOC's have a channel by that name)",
|
||||
"Identical process variable name on multiple servers",
|
||||
"The CA routine called is inappropriate for use within an event handler",
|
||||
"Database value get for that channel failed during channel search",
|
||||
"Unable to initialize without the vxWorks VX_FP_TASK task option set",
|
||||
@@ -176,7 +175,6 @@ READONLY char *ca_message_text[]
|
||||
"Data conversion between client's type and the server's type failed",
|
||||
"Invalid channel identifier",
|
||||
"Invalid function pointer",
|
||||
"Operation will block (this code is not returned to user)",
|
||||
"Thread is already attached to a client context"
|
||||
};
|
||||
#endif
|
||||
|
||||
+5
-5
@@ -83,7 +83,7 @@ unsigned *pInlineIter
|
||||
/*
|
||||
* test_search ()
|
||||
*/
|
||||
LOCAL void test_search(
|
||||
LOCAL void test_search (
|
||||
ti *pItems,
|
||||
unsigned iterations,
|
||||
unsigned *pInlineIter
|
||||
@@ -92,12 +92,12 @@ unsigned *pInlineIter
|
||||
unsigned i;
|
||||
int status;
|
||||
|
||||
for (i=0u; i<iterations; i++) {
|
||||
status = ca_search (pItems[i].name, &pItems[i].chix);
|
||||
for ( i = 0u; i < iterations; i++ ) {
|
||||
status = ca_search ( pItems[i].name, &pItems[i].chix );
|
||||
SEVCHK (status, NULL);
|
||||
}
|
||||
status = ca_pend_io(0.0);
|
||||
SEVCHK (status, NULL);
|
||||
status = ca_pend_io ( 0.0 );
|
||||
SEVCHK ( status, NULL );
|
||||
|
||||
*pInlineIter = 1;
|
||||
}
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
|
||||
static const unsigned defaultIterations = 10000u;
|
||||
|
||||
int main(int argc, char **argv)
|
||||
int main ( int argc, char **argv )
|
||||
{
|
||||
const char *pUsage = "<channel name> [<channel count> [<if 3rd arg present append number to pv name>]]";
|
||||
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
|
||||
/* $Id$
|
||||
*
|
||||
* L O S A L A M O S
|
||||
* Los Alamos National Laboratory
|
||||
* Los Alamos, New Mexico 87545
|
||||
*
|
||||
* Copyright, 1986, The Regents of the University of California.
|
||||
*
|
||||
* Author: Jeff Hill
|
||||
*/
|
||||
|
||||
#include "iocinf.h"
|
||||
|
||||
bool claimMsgCache::set ( nciu & chan )
|
||||
{
|
||||
this->clientId = chan.id;
|
||||
this->serverId = chan.sid;
|
||||
if ( this->v44 ) {
|
||||
unsigned len = strlen ( chan.pNameStr ) + 1u;
|
||||
if ( this->bufLen < len ) {
|
||||
unsigned newBufLen = 2 * len;
|
||||
char *pNewStr = new char [ newBufLen ];
|
||||
if ( pNewStr ) {
|
||||
delete [] this->pStr;
|
||||
this->pStr = pNewStr;
|
||||
this->bufLen = newBufLen;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
strcpy ( this->pStr, chan.pNameStr );
|
||||
this->currentStrLen = len;
|
||||
}
|
||||
else {
|
||||
this->currentStrLen = 0u;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
|
||||
/* $Id$
|
||||
*
|
||||
* L O S A L A M O S
|
||||
* Los Alamos National Laboratory
|
||||
* Los Alamos, New Mexico 87545
|
||||
*
|
||||
* Copyright, 1986, The Regents of the University of California.
|
||||
*
|
||||
* Author: Jeff Hill
|
||||
*/
|
||||
|
||||
inline claimMsgCache::claimMsgCache ( bool v44In ) :
|
||||
pStr ( 0 ), clientId ( UINT_MAX ), serverId ( UINT_MAX ), currentStrLen ( 0u ),
|
||||
bufLen ( 0u ), v44 ( v44In )
|
||||
{
|
||||
}
|
||||
|
||||
inline claimMsgCache::~claimMsgCache ()
|
||||
{
|
||||
if ( this->pStr ) {
|
||||
delete this->pStr;
|
||||
}
|
||||
}
|
||||
|
||||
inline int claimMsgCache::deliverMsg ( tcpiiu &iiu )
|
||||
{
|
||||
if ( v44 ) {
|
||||
return iiu.createChannelRequest ( this->clientId, this->pStr, this->currentStrLen );
|
||||
}
|
||||
else {
|
||||
return iiu.createChannelRequest ( this->serverId, 0u, 0u );
|
||||
}
|
||||
}
|
||||
|
||||
inline bool claimMsgCache::channelMatches ( class nciu &chan )
|
||||
{
|
||||
return chan.id == this->clientId;
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
|
||||
/* $Id$
|
||||
*
|
||||
* L O S A L A M O S
|
||||
* Los Alamos National Laboratory
|
||||
* Los Alamos, New Mexico 87545
|
||||
*
|
||||
* Copyright, 1986, The Regents of the University of California.
|
||||
*
|
||||
* Author: Jeff Hill
|
||||
*/
|
||||
|
||||
#include "iocinf.h"
|
||||
#include "netiiu_IL.h"
|
||||
|
||||
claimsPendingIIU::claimsPendingIIU ( tcpiiu &tcpIIUIn ) :
|
||||
netiiu ( tcpIIUIn.clientCtx () ), tcpIIU ( tcpIIUIn )
|
||||
{
|
||||
}
|
||||
|
||||
claimsPendingIIU::~claimsPendingIIU ()
|
||||
{
|
||||
}
|
||||
|
||||
const char * claimsPendingIIU::pHostName () const
|
||||
{
|
||||
return this->tcpIIU.pHostName ();
|
||||
}
|
||||
|
||||
void claimsPendingIIU::hostName ( char *pBuf, unsigned bufLength ) const
|
||||
{
|
||||
this->tcpIIU.hostName ( pBuf, bufLength );
|
||||
}
|
||||
|
||||
bool claimsPendingIIU::connectionInProgress ( const char *pChannelName, const osiSockAddr &addr ) const
|
||||
{
|
||||
return this->tcpIIU.connectionInProgress ( pChannelName, addr );
|
||||
}
|
||||
@@ -0,0 +1,239 @@
|
||||
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
*
|
||||
* L O S A L A M O S
|
||||
* Los Alamos National Laboratory
|
||||
* Los Alamos, New Mexico 87545
|
||||
*
|
||||
* Copyright, 1986, The Regents of the University of California.
|
||||
*
|
||||
*
|
||||
* Author Jeffrey O. Hill
|
||||
* johill@lanl.gov
|
||||
*/
|
||||
|
||||
#ifndef comBuf_ILh
|
||||
#define comBuf_ILh
|
||||
|
||||
#include <assert.h>
|
||||
#include "epicsTypes.h"
|
||||
#include "osiWireFormat.h"
|
||||
|
||||
inline comBuf::comBuf () : nextWriteIndex ( 0u ), nextReadIndex ( 0u )
|
||||
{
|
||||
}
|
||||
|
||||
inline comBuf::~comBuf ()
|
||||
{
|
||||
}
|
||||
|
||||
inline void comBuf::destroy ()
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
inline void * comBuf::operator new ( size_t size )
|
||||
{
|
||||
return comBuf::freeList.allocate ( size );
|
||||
}
|
||||
|
||||
inline void comBuf::operator delete ( void *pCadaver, size_t size )
|
||||
{
|
||||
comBuf::freeList.release ( pCadaver, size );
|
||||
}
|
||||
|
||||
inline unsigned comBuf::unoccupiedBytes () const
|
||||
{
|
||||
return sizeof ( this->buf ) - this->nextWriteIndex;
|
||||
}
|
||||
|
||||
inline unsigned comBuf::occupiedBytes () const
|
||||
{
|
||||
return this->nextWriteIndex - this->nextReadIndex;
|
||||
}
|
||||
|
||||
inline bool comBuf::copyInAllBytes ( const void *pBuf, unsigned nBytes )
|
||||
{
|
||||
if ( nBytes > this->unoccupiedBytes () ) {
|
||||
return false;
|
||||
}
|
||||
memcpy ( &this->buf[this->nextWriteIndex], pBuf, nBytes);
|
||||
this->nextWriteIndex += nBytes;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline unsigned comBuf::copyInBytes ( const void *pBuf, unsigned nBytes )
|
||||
{
|
||||
unsigned available = this->unoccupiedBytes ();
|
||||
if ( nBytes > available ) {
|
||||
nBytes = available;
|
||||
}
|
||||
memcpy ( &this->buf[this->nextWriteIndex], pBuf, nBytes);
|
||||
this->nextWriteIndex += nBytes;
|
||||
return nBytes;
|
||||
}
|
||||
|
||||
inline unsigned comBuf::copyIn ( comBuf &bufIn )
|
||||
{
|
||||
unsigned nBytes = this->copyInBytes ( &bufIn.buf[bufIn.nextReadIndex],
|
||||
bufIn.nextWriteIndex - bufIn.nextReadIndex );
|
||||
bufIn.nextReadIndex += nBytes;
|
||||
return nBytes;
|
||||
}
|
||||
|
||||
inline bool comBuf::copyOutAllBytes ( void *pBuf, unsigned nBytes )
|
||||
{
|
||||
if ( nBytes > this->occupiedBytes () ) {
|
||||
return false;
|
||||
}
|
||||
memcpy ( pBuf, &this->buf[this->nextReadIndex], nBytes);
|
||||
this->nextReadIndex += nBytes;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline unsigned comBuf::copyOutBytes ( void *pBuf, unsigned nBytes )
|
||||
{
|
||||
unsigned occupied = this->occupiedBytes ();
|
||||
if ( nBytes > occupied ) {
|
||||
nBytes = occupied;
|
||||
}
|
||||
memcpy ( pBuf, &this->buf[this->nextReadIndex], nBytes);
|
||||
this->nextReadIndex += nBytes;
|
||||
return nBytes;
|
||||
}
|
||||
|
||||
inline unsigned comBuf::removeBytes ( unsigned nBytes )
|
||||
{
|
||||
unsigned occupied = this->occupiedBytes ();
|
||||
if ( nBytes > occupied ) {
|
||||
nBytes = occupied;
|
||||
}
|
||||
this->nextReadIndex += nBytes;
|
||||
return nBytes;
|
||||
}
|
||||
|
||||
inline unsigned comBuf::maxBytes ()
|
||||
{
|
||||
return comBufSize;
|
||||
}
|
||||
|
||||
inline bool comBuf::flushToWire ( class comQueSend &que )
|
||||
{
|
||||
unsigned occupied = this->occupiedBytes ();
|
||||
|
||||
unsigned nSent = 0u;
|
||||
while ( occupied ) {
|
||||
unsigned nBytes = que.sendBytes ( &this->buf[this->nextReadIndex], occupied );
|
||||
if ( nBytes == 0u ) {
|
||||
this->nextReadIndex = this->nextWriteIndex;
|
||||
return false;
|
||||
}
|
||||
this->nextReadIndex += nBytes;
|
||||
occupied = this->occupiedBytes ();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
inline unsigned comBuf::fillFromWire ( class comQueRecv &que )
|
||||
{
|
||||
unsigned nNewBytes = que.recvBytes ( &this->buf[this->nextWriteIndex],
|
||||
sizeof ( this->buf ) - this->nextWriteIndex );
|
||||
this->nextWriteIndex += nNewBytes;
|
||||
return nNewBytes;
|
||||
}
|
||||
|
||||
inline unsigned comBuf::clipNElem ( unsigned elemSize, unsigned nElem )
|
||||
{
|
||||
unsigned avail = this->unoccupiedBytes ();
|
||||
if ( elemSize * nElem > avail ) {
|
||||
return avail / elemSize;
|
||||
}
|
||||
else {
|
||||
return nElem;
|
||||
}
|
||||
}
|
||||
|
||||
inline unsigned comBuf::copyIn ( const epicsInt8 *pValue, unsigned nElem )
|
||||
{
|
||||
return copyInBytes ( pValue, nElem );
|
||||
}
|
||||
|
||||
inline unsigned comBuf::copyIn ( const epicsUInt8 *pValue, unsigned nElem )
|
||||
{
|
||||
return copyInBytes ( pValue, nElem );
|
||||
}
|
||||
|
||||
inline unsigned comBuf::copyIn ( const epicsOldString *pValue, unsigned nElem )
|
||||
{
|
||||
return copyInBytes ( pValue, nElem * sizeof ( *pValue ) );
|
||||
}
|
||||
|
||||
inline unsigned comBuf::copyIn ( const epicsInt16 *pValue, unsigned nElem )
|
||||
{
|
||||
nElem = this->clipNElem ( sizeof (*pValue), nElem );
|
||||
for ( unsigned i = 0u; i < nElem; i++ ) {
|
||||
this->buf[this->nextWriteIndex++] = pValue[i] >> 8u;
|
||||
this->buf[this->nextWriteIndex++] = pValue[i] >> 0u;
|
||||
}
|
||||
return nElem;
|
||||
}
|
||||
|
||||
inline unsigned comBuf::copyIn ( const epicsUInt16 *pValue, unsigned nElem )
|
||||
{
|
||||
nElem = this->clipNElem ( sizeof (*pValue), nElem );
|
||||
for ( unsigned i = 0u; i < nElem; i++ ) {
|
||||
this->buf[this->nextWriteIndex++] = pValue[i] >> 8u;
|
||||
this->buf[this->nextWriteIndex++] = pValue[i] >> 0u;
|
||||
}
|
||||
return nElem;
|
||||
}
|
||||
|
||||
inline unsigned comBuf::copyIn ( const epicsInt32 *pValue, unsigned nElem )
|
||||
{
|
||||
nElem = this->clipNElem ( sizeof (*pValue), nElem );
|
||||
for ( unsigned i = 0u; i < nElem; i++ ) {
|
||||
this->buf[this->nextWriteIndex++] = pValue[i] >> 24u;
|
||||
this->buf[this->nextWriteIndex++] = pValue[i] >> 16u;
|
||||
this->buf[this->nextWriteIndex++] = pValue[i] >> 8u;
|
||||
this->buf[this->nextWriteIndex++] = pValue[i] >> 0u;
|
||||
}
|
||||
return nElem;
|
||||
}
|
||||
|
||||
inline unsigned comBuf::copyIn ( const epicsUInt32 *pValue, unsigned nElem )
|
||||
{
|
||||
nElem = this->clipNElem ( sizeof (*pValue), nElem );
|
||||
for ( unsigned i = 0u; i < nElem; i++ ) {
|
||||
this->buf[this->nextWriteIndex++] = pValue[i] >> 24u;
|
||||
this->buf[this->nextWriteIndex++] = pValue[i] >> 16u;
|
||||
this->buf[this->nextWriteIndex++] = pValue[i] >> 8u;
|
||||
this->buf[this->nextWriteIndex++] = pValue[i] >> 0u;
|
||||
}
|
||||
return nElem;
|
||||
}
|
||||
|
||||
inline unsigned comBuf::copyIn ( const epicsFloat32 *pValue, unsigned nElem )
|
||||
{
|
||||
nElem = this->clipNElem ( sizeof (*pValue), nElem );
|
||||
for ( unsigned i = 0u; i < nElem; i++ ) {
|
||||
// allow native floating point formats to be converted to IEEE
|
||||
osiConvertToWireFormat ( pValue[i], &this->buf[this->nextWriteIndex] );
|
||||
this->nextWriteIndex += 4u;
|
||||
}
|
||||
return nElem;
|
||||
}
|
||||
|
||||
inline unsigned comBuf::copyIn ( const epicsFloat64 *pValue, unsigned nElem )
|
||||
{
|
||||
nElem = this->clipNElem ( sizeof (*pValue), nElem );
|
||||
for ( unsigned i = 0u; i < nElem; i++ ) {
|
||||
// allow native floating point formats to be converted to IEEE
|
||||
osiConvertToWireFormat ( pValue[i], &this->buf[this->nextWriteIndex] );
|
||||
this->nextWriteIndex += 8u;
|
||||
}
|
||||
return nElem;
|
||||
}
|
||||
|
||||
#endif // comBuf_ILh
|
||||
@@ -0,0 +1,113 @@
|
||||
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
*
|
||||
* L O S A L A M O S
|
||||
* Los Alamos National Laboratory
|
||||
* Los Alamos, New Mexico 87545
|
||||
*
|
||||
* Copyright, 1986, The Regents of the University of California.
|
||||
*
|
||||
*
|
||||
* Author Jeffrey O. Hill
|
||||
* johill@lanl.gov
|
||||
*/
|
||||
|
||||
#include <iocinf.h>
|
||||
#include <comBuf_IL.h>
|
||||
|
||||
comQueRecv::~comQueRecv ()
|
||||
{
|
||||
comBuf *pBuf;
|
||||
|
||||
this->mutex.lock ();
|
||||
while ( ( pBuf = this->bufs.get () ) ) {
|
||||
pBuf->destroy ();
|
||||
}
|
||||
this->mutex.unlock ();
|
||||
}
|
||||
|
||||
unsigned comQueRecv::occupiedBytes () const
|
||||
{
|
||||
this->mutex.lock ();
|
||||
|
||||
unsigned count = this->bufs.count ();
|
||||
unsigned nBytes;
|
||||
if ( count >= 2u ) {
|
||||
nBytes = this->bufs.first ()->occupiedBytes ();
|
||||
nBytes += this->bufs.last ()->occupiedBytes ();
|
||||
nBytes += ( count - 2u ) * comBuf::maxBytes ();
|
||||
}
|
||||
else if ( count == 1u ) {
|
||||
nBytes = this->bufs.first ()->occupiedBytes ();
|
||||
}
|
||||
else {
|
||||
nBytes = 0u;
|
||||
}
|
||||
|
||||
this->mutex.unlock ();
|
||||
|
||||
return nBytes;
|
||||
}
|
||||
|
||||
bool comQueRecv::copyOutBytes ( void *pBuf, unsigned nBytes )
|
||||
{
|
||||
char *pCharBuf = static_cast < char * > ( pBuf );
|
||||
|
||||
this->mutex.lock ();
|
||||
|
||||
// dont return partial message
|
||||
if ( nBytes > this->occupiedBytes () ) {
|
||||
this->mutex.unlock ();
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned bytesLeft = nBytes;
|
||||
while ( bytesLeft ) {
|
||||
comBuf * pComBuf = this->bufs.first ();
|
||||
assert ( pComBuf );
|
||||
bytesLeft -= pComBuf->copyOutBytes ( &pCharBuf[nBytes-bytesLeft], bytesLeft );
|
||||
if ( pComBuf->occupiedBytes () == 0u ) {
|
||||
this->bufs.remove ( *pComBuf );
|
||||
pComBuf->destroy ();
|
||||
}
|
||||
}
|
||||
|
||||
this->mutex.unlock ();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned comQueRecv::fillFromWire ()
|
||||
{
|
||||
// this approach requires that only one thread performs fill
|
||||
// but its advantage is that the lock is not held while filling
|
||||
|
||||
comBuf *pComBuf = new comBuf;
|
||||
if ( ! pComBuf ) {
|
||||
// no way to be informed when memory is available
|
||||
threadSleep ( 0.5 );
|
||||
return 0u;
|
||||
}
|
||||
|
||||
unsigned nNewBytes = pComBuf->fillFromWire ( *this );
|
||||
|
||||
this->mutex.lock ();
|
||||
|
||||
comBuf *pLastBuf = this->bufs.last ();
|
||||
if ( pLastBuf ) {
|
||||
pLastBuf->copyIn ( *pComBuf );
|
||||
}
|
||||
if ( pComBuf->occupiedBytes () ) {
|
||||
this->bufs.add ( *pComBuf );
|
||||
}
|
||||
else {
|
||||
pComBuf->destroy ();
|
||||
}
|
||||
|
||||
this->mutex.unlock ();
|
||||
|
||||
return nNewBytes;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,814 @@
|
||||
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
*
|
||||
* L O S A L A M O S
|
||||
* Los Alamos National Laboratory
|
||||
* Los Alamos, New Mexico 87545
|
||||
*
|
||||
* Copyright, 1986, The Regents of the University of California.
|
||||
*
|
||||
*
|
||||
* Author Jeffrey O. Hill
|
||||
* johill@lanl.gov
|
||||
*/
|
||||
|
||||
//
|
||||
// Requirements:
|
||||
// 1) Allow sufficent headroom so that users will be able to perform
|
||||
// a reasonable amount of IO within CA callbacks without experiencing
|
||||
// a push/pull deadlock. If a potential push/pull deadlock situation
|
||||
// occurs then detect and avoid it and provide diagnotic to the user
|
||||
// via special status.
|
||||
// 2) Return status to the user when there is insufficent memory to
|
||||
// queue a complete message.
|
||||
// 3) return status to the user when a message cant be flushed because
|
||||
// a connection dropped.
|
||||
// 4) Do not allocate too much memory in exception situatons (such as
|
||||
// after a circuit disconnect).
|
||||
// 5) Avoid allocating more memory than is absolutely necessary to meet
|
||||
// the above requirements.
|
||||
// 6) Message fragments must never be sent to the IOC when there isnt
|
||||
// enough memory to queue part of a message (we also must not force
|
||||
// a disconnect because the client is starved for memory).
|
||||
// 7) avoid the need to check status for each byte pushed into the
|
||||
// protocol stream.
|
||||
//
|
||||
// Implementation:
|
||||
// 1) When queuing a complete message, first test to see if a flush is
|
||||
// required. If it is a receive thread schedual the flush with the
|
||||
// send thread, and otherwise directly execute the system call. The
|
||||
// send thread must run at a higher priority than the receive thread
|
||||
// if we are to minimize memory consumption.
|
||||
// 2) Preallocate space for the entire message prior to copying in the
|
||||
// message so that message fragments are not flushed out just prior
|
||||
// to detecting that memory is unavailable.
|
||||
// 3) Return a special error constant when the following situations
|
||||
// are detected when the user is attempting to queue a request
|
||||
// from within a user callback executed by a receive thread:
|
||||
// a) A user is queuing more requests that demand a response from a
|
||||
// callback than are removed by the response that initiated the
|
||||
// callback, and this situation persists for many callbacks until
|
||||
// all buffering in the system is exausted.
|
||||
// b) A user is queuing many requests that demand a response from one
|
||||
// callback until all buffering in the system is exausted.
|
||||
// c) Some combination of both (a) nad (b).
|
||||
//
|
||||
//
|
||||
|
||||
#include <iocinf.h>
|
||||
#include <comBuf_IL.h>
|
||||
|
||||
tsFreeList < class comBuf, 0x20, true > comBuf::freeList;
|
||||
|
||||
// nill message pad bytes
|
||||
static const char nillBytes[] =
|
||||
{
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0
|
||||
};
|
||||
|
||||
inline bufferReservoir::~bufferReservoir ()
|
||||
{
|
||||
comBuf *pBuf;
|
||||
while ( pBuf = this->reservedBufs.get () ) {
|
||||
pBuf->destroy ();
|
||||
}
|
||||
}
|
||||
|
||||
inline comBuf *bufferReservoir::fetchOneBuffer ()
|
||||
{
|
||||
return this->reservedBufs.get ();
|
||||
}
|
||||
|
||||
inline bool bufferReservoir::addOneBuffer ()
|
||||
{
|
||||
comBuf *pBuf = new comBuf;
|
||||
if ( pBuf ) {
|
||||
this->reservedBufs.add ( *pBuf );
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
inline unsigned bufferReservoir::nBytes ()
|
||||
{
|
||||
return ( this->reservedBufs.count () * comBuf::maxBytes () );
|
||||
}
|
||||
|
||||
// o lock the comQueSend
|
||||
// o reserve sufficent space for entire message
|
||||
// (this allows the recv thread to add a message
|
||||
// to the que while some other thread is flushing
|
||||
// and therefore prevents deadlocks, and it also
|
||||
// allows proper status to be returned)
|
||||
// o unlock comQueSend if status is not ECA_NORMAL
|
||||
inline int comQueSend::lockAndReserveSpace ( unsigned msgSize, bufferReservoir &reservoir )
|
||||
{
|
||||
unsigned bytesReserved = reservoir.nBytes ();
|
||||
unsigned unoccupied;
|
||||
|
||||
this->mutex.lock ();
|
||||
|
||||
comBuf *pComBuf = this->bufs.last ();
|
||||
if ( pComBuf ) {
|
||||
unoccupied = pComBuf->unoccupiedBytes ();
|
||||
}
|
||||
else {
|
||||
unoccupied = 0u;
|
||||
}
|
||||
|
||||
// flush if conditions indicate. second part of this guarantees
|
||||
// that we will not flush out a buffer with almost nothing
|
||||
// in it (this has a large impact on performance)
|
||||
if ( this->bufs.count () <= 1u || unoccupied >= msgSize ) {
|
||||
bytesReserved = unoccupied;
|
||||
}
|
||||
else {
|
||||
this->mutex.unlock ();
|
||||
if ( ! this->flushToWire () ) {
|
||||
return ECA_DISCONNCHID;
|
||||
}
|
||||
if ( this->bufs.count () >= 32u ) {
|
||||
return ECA_TOLARGE;
|
||||
}
|
||||
this->mutex.lock ();
|
||||
}
|
||||
|
||||
while ( bytesReserved < msgSize ) {
|
||||
if ( reservoir.addOneBuffer() ) {
|
||||
bytesReserved += comBuf::maxBytes ();
|
||||
}
|
||||
else {
|
||||
this->mutex.unlock ();
|
||||
return ECA_ALLOCMEM;
|
||||
}
|
||||
}
|
||||
|
||||
return ECA_NORMAL;
|
||||
}
|
||||
|
||||
// 1) This routine is private because it assumes that the lock
|
||||
// is applied
|
||||
//
|
||||
// 2) This routine does not return status because of the following
|
||||
// argument. The routine can fail because the wire disconnects or
|
||||
// because their isnt memory to create a buffer. For the former we
|
||||
// just discard the message, but do not fail. For the latter we
|
||||
// shutdown() the connection and discard the rest of the message
|
||||
// (this eliminates the possibility of message fragments getting
|
||||
// onto the wire).
|
||||
//
|
||||
// 3) Arguments here are a bit verbose until compilers all implement
|
||||
// member template functions.
|
||||
//
|
||||
|
||||
template < class T >
|
||||
inline void comQueSend_copyIn ( tsDLList < comBuf > &comBufList,
|
||||
bufferReservoir &reservoir, const T *pVal, unsigned nElem )
|
||||
{
|
||||
unsigned nCopied;
|
||||
|
||||
comBuf *pComBuf = comBufList.last ();
|
||||
if ( pComBuf ) {
|
||||
nCopied = pComBuf->copyIn ( pVal, nElem );
|
||||
}
|
||||
else {
|
||||
nCopied = 0u;
|
||||
}
|
||||
|
||||
while ( nElem > nCopied ) {
|
||||
pComBuf = reservoir.fetchOneBuffer ();
|
||||
//
|
||||
// This fails only if space was not preallocated.
|
||||
// See comments at the top of this program on
|
||||
// why space must always be preallocated.
|
||||
//
|
||||
assert ( pComBuf );
|
||||
nCopied += pComBuf->copyIn ( &pVal[nCopied], nElem - nCopied );
|
||||
comBufList.add ( *pComBuf );
|
||||
}
|
||||
}
|
||||
|
||||
template < class T >
|
||||
inline void comQueSend_copyIn ( tsDLList < comBuf > &comBufList, bufferReservoir &reservoir, const T &val )
|
||||
{
|
||||
comBuf *pComBuf = comBufList.last ();
|
||||
if ( pComBuf ) {
|
||||
if ( pComBuf->copyIn ( &val, 1u ) >= 1u ) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
pComBuf = reservoir.fetchOneBuffer ();
|
||||
//
|
||||
// This fails only if space was not preallocated.
|
||||
// See comments at the top of this program on
|
||||
// space must always be preallocated.
|
||||
//
|
||||
assert ( pComBuf );
|
||||
pComBuf->copyIn ( &val, 1u );
|
||||
comBufList.add ( *pComBuf );
|
||||
}
|
||||
|
||||
void comQueSend::copy_dbr_string ( bufferReservoir &reservoir, const void *pValue, unsigned nElem )
|
||||
{
|
||||
comQueSend_copyIn ( this->bufs, reservoir, static_cast <const dbr_string_t *> ( pValue ), nElem );
|
||||
}
|
||||
|
||||
void comQueSend::copy_dbr_short ( bufferReservoir &reservoir, const void *pValue, unsigned nElem )
|
||||
{
|
||||
comQueSend_copyIn ( this->bufs, reservoir, static_cast <const dbr_short_t *> ( pValue ), nElem );
|
||||
}
|
||||
|
||||
void comQueSend::copy_dbr_float ( bufferReservoir &reservoir, const void *pValue, unsigned nElem )
|
||||
{
|
||||
comQueSend_copyIn ( this->bufs, reservoir, static_cast <const dbr_float_t *> ( pValue ), nElem );
|
||||
}
|
||||
|
||||
void comQueSend::copy_dbr_char ( bufferReservoir &reservoir, const void *pValue, unsigned nElem )
|
||||
{
|
||||
comQueSend_copyIn ( this->bufs, reservoir, static_cast <const dbr_char_t *> ( pValue ), nElem );
|
||||
}
|
||||
|
||||
void comQueSend::copy_dbr_long ( bufferReservoir &reservoir, const void *pValue, unsigned nElem )
|
||||
{
|
||||
comQueSend_copyIn ( this->bufs, reservoir, static_cast <const dbr_long_t *> ( pValue ), nElem );
|
||||
}
|
||||
|
||||
void comQueSend::copy_dbr_double ( bufferReservoir &reservoir, const void *pValue, unsigned nElem )
|
||||
{
|
||||
comQueSend_copyIn ( this->bufs, reservoir, static_cast <const dbr_double_t *> ( pValue ), nElem );
|
||||
}
|
||||
|
||||
const comQueSend::copyFunc_t comQueSend::dbrCopyVector [] = {
|
||||
comQueSend::copy_dbr_string,
|
||||
comQueSend::copy_dbr_short,
|
||||
comQueSend::copy_dbr_float,
|
||||
comQueSend::copy_dbr_short, // DBR_ENUM
|
||||
comQueSend::copy_dbr_char,
|
||||
comQueSend::copy_dbr_long,
|
||||
comQueSend::copy_dbr_double,
|
||||
0, // DBR_STS_SHORT
|
||||
0, // DBR_STS_FLOAT
|
||||
0, // DBR_STS_ENUM
|
||||
0, // DBR_STS_CHAR
|
||||
0, // DBR_STS_LONG
|
||||
0, // DBR_STS_DOUBLE
|
||||
0, // DBR_TIME_STRING
|
||||
0, // DBR_TIME_INT
|
||||
0, // DBR_TIME_SHORT
|
||||
0, // DBR_TIME_FLOAT
|
||||
0, // DBR_TIME_ENUM
|
||||
0, // DBR_TIME_CHAR
|
||||
0, // DBR_TIME_LONG
|
||||
0, // DBR_TIME_DOUBLE
|
||||
0, // DBR_GR_STRING
|
||||
0, // DBR_GR_SHORT
|
||||
0, // DBR_GR_FLOAT
|
||||
0, // DBR_GR_ENUM
|
||||
0, // DBR_GR_CHAR
|
||||
0, // DBR_GR_LONG
|
||||
0, // DBR_GR_DOUBLE
|
||||
0, // DBR_CTRL_STRING
|
||||
0, // DBR_CTRL_SHORT
|
||||
0, // DBR_CTRL_FLOAT
|
||||
0, // DBR_CTRL_ENUM
|
||||
0, // DBR_CTRL_CHAR
|
||||
0, // DBR_CTRL_LONG
|
||||
0, // DBR_CTRL_DOUBLE
|
||||
comQueSend::copy_dbr_short, // DBR_PUT_ACKT
|
||||
comQueSend::copy_dbr_short, // DBR_PUT_ACKS
|
||||
0, // DBR_STSACK_STRING
|
||||
0 // DBR_CLASS_NAME
|
||||
};
|
||||
|
||||
comQueSend::~comQueSend ()
|
||||
{
|
||||
comBuf *pBuf;
|
||||
|
||||
this->mutex.lock ();
|
||||
while ( ( pBuf = this->bufs.get () ) ) {
|
||||
pBuf->destroy ();
|
||||
}
|
||||
this->mutex.unlock ();
|
||||
}
|
||||
|
||||
unsigned comQueSend::occupiedBytes () const
|
||||
{
|
||||
this->mutex.lock ();
|
||||
|
||||
unsigned count = this->bufs.count ();
|
||||
unsigned nBytes;
|
||||
if ( count >= 2u ) {
|
||||
nBytes = this->bufs.first ()->occupiedBytes ();
|
||||
nBytes += this->bufs.last ()->occupiedBytes ();
|
||||
nBytes += ( count - 2u ) * comBuf::maxBytes ();
|
||||
}
|
||||
else if ( count == 1u ) {
|
||||
nBytes = this->bufs.first ()->occupiedBytes ();
|
||||
}
|
||||
else {
|
||||
nBytes = 0u;
|
||||
}
|
||||
|
||||
this->mutex.unlock ();
|
||||
|
||||
return nBytes;
|
||||
}
|
||||
|
||||
bool comQueSend::flushToWire ()
|
||||
{
|
||||
bool success;
|
||||
|
||||
// the recv thread is not permitted to flush as this
|
||||
// can result in a push / pull deadlock on the TCP pipe,
|
||||
// but in that case this does schedual the flush through
|
||||
// the higher priority send thread
|
||||
if ( ! this->flushToWirePermit () ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// this approach requires that only one thread at a time
|
||||
// performs flushes but its advantage is that the primary
|
||||
// lock is not held while sending and this prevents deadlocks
|
||||
this->flushMutex.lock ();
|
||||
|
||||
while ( true ) {
|
||||
this->mutex.lock ();
|
||||
comBuf * pBuf = this->bufs.get ();
|
||||
this->mutex.unlock ();
|
||||
if ( ! pBuf ) {
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
bool success = pBuf->flushToWire ( *this );
|
||||
pBuf->destroy ();
|
||||
if ( ! success ) {
|
||||
comBuf *pBuf;
|
||||
|
||||
this->mutex.lock ();
|
||||
while ( ( pBuf = this->bufs.get () ) ) {
|
||||
pBuf->destroy ();
|
||||
}
|
||||
this->mutex.unlock ();
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
this->flushMutex.unlock ();
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
int comQueSend::writeRequest ( unsigned serverId, unsigned type, unsigned nElem, const void *pValue )
|
||||
{
|
||||
bufferReservoir reservoir;
|
||||
unsigned size, postcnt;
|
||||
bool stringOptim;
|
||||
|
||||
if ( ! this->dbrCopyVector [type] ) {
|
||||
return ECA_BADTYPE;
|
||||
}
|
||||
if ( nElem > 0xffff) {
|
||||
return ECA_BADCOUNT;
|
||||
}
|
||||
|
||||
if ( type == DBR_STRING && nElem == 1 ) {
|
||||
char *pstr = (char *) pValue;
|
||||
size = strlen ( pstr ) +1;
|
||||
stringOptim = true;
|
||||
}
|
||||
else {
|
||||
size = dbr_size_n ( type, nElem );
|
||||
stringOptim = false;
|
||||
}
|
||||
|
||||
postcnt = CA_MESSAGE_ALIGN ( size );
|
||||
if ( postcnt > 0xffff ) {
|
||||
return ECA_BADCOUNT;
|
||||
}
|
||||
|
||||
assert ( serverId <= 0xffffffff );
|
||||
|
||||
int status = this->lockAndReserveSpace ( postcnt + 16u, reservoir );
|
||||
if ( status == ECA_NORMAL ) {
|
||||
comQueSend_copyIn ( this->bufs, reservoir, static_cast <ca_uint16_t> ( CA_PROTO_WRITE ) ); // cmd
|
||||
comQueSend_copyIn ( this->bufs, reservoir, static_cast <ca_uint16_t> ( postcnt ) ); // postsize
|
||||
comQueSend_copyIn ( this->bufs, reservoir, static_cast <ca_uint16_t> ( type ) ); // dataType
|
||||
comQueSend_copyIn ( this->bufs, reservoir, static_cast <ca_uint16_t> ( nElem ) ); // count
|
||||
comQueSend_copyIn ( this->bufs, reservoir, static_cast <ca_uint32_t> ( serverId ) ); // cid
|
||||
comQueSend_copyIn ( this->bufs, reservoir, static_cast <ca_uint32_t> ( ~0UL ) ); // available
|
||||
if ( stringOptim ) {
|
||||
comQueSend_copyIn ( this->bufs, reservoir, static_cast <const unsigned char *> ( pValue ), size );
|
||||
}
|
||||
else {
|
||||
( this->*dbrCopyVector [type] ) ( reservoir, pValue, nElem );
|
||||
}
|
||||
comQueSend_copyIn ( this->bufs, reservoir, nillBytes, postcnt - size );
|
||||
this->mutex.unlock ();
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
int comQueSend::writeNotifyRequest ( unsigned ioId, unsigned serverId, unsigned type, unsigned nElem, const void *pValue )
|
||||
{
|
||||
bufferReservoir reservoir;
|
||||
ca_uint32_t size, postcnt;
|
||||
|
||||
if ( ! this->dbrCopyVector [type] ) {
|
||||
return ECA_BADTYPE;
|
||||
}
|
||||
if ( nElem > 0xffff) {
|
||||
return ECA_BADCOUNT;
|
||||
}
|
||||
|
||||
if ( type == DBR_STRING && nElem == 1 ) {
|
||||
char *pstr = (char *) pValue;
|
||||
size = strlen ( pstr ) +1;
|
||||
}
|
||||
else {
|
||||
size = dbr_size_n ( type, nElem );
|
||||
}
|
||||
postcnt = CA_MESSAGE_ALIGN ( size );
|
||||
if ( postcnt > 0xffff ) {
|
||||
return ECA_BADCOUNT;
|
||||
}
|
||||
|
||||
assert ( serverId <= 0xffffffff );
|
||||
|
||||
int status = this->lockAndReserveSpace ( postcnt + 16u, reservoir );
|
||||
if ( status == ECA_NORMAL ) {
|
||||
comQueSend_copyIn ( this->bufs, reservoir, static_cast <ca_uint16_t> ( CA_PROTO_WRITE_NOTIFY ) ); // cmd
|
||||
comQueSend_copyIn ( this->bufs, reservoir, static_cast <ca_uint16_t> ( postcnt ) ); // postsize
|
||||
comQueSend_copyIn ( this->bufs, reservoir, static_cast <ca_uint16_t> ( type ) ); // dataType
|
||||
comQueSend_copyIn ( this->bufs, reservoir, static_cast <ca_uint16_t> ( nElem ) ); // count
|
||||
comQueSend_copyIn ( this->bufs, reservoir, static_cast <ca_uint32_t> ( serverId ) ); // cid
|
||||
comQueSend_copyIn ( this->bufs, reservoir, static_cast <ca_uint32_t> ( ioId ) ); // available
|
||||
( this->*dbrCopyVector [type] ) ( reservoir, pValue, nElem );
|
||||
comQueSend_copyIn ( this->bufs, reservoir, nillBytes, postcnt - size );
|
||||
this->mutex.unlock ();
|
||||
}
|
||||
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
int comQueSend::readCopyRequest ( unsigned ioId, unsigned serverId, unsigned type, unsigned nElem )
|
||||
{
|
||||
bufferReservoir reservoir;
|
||||
|
||||
if ( nElem > 0xffff) {
|
||||
return ECA_BADCOUNT;
|
||||
}
|
||||
if ( type > 0xffff) {
|
||||
return ECA_BADTYPE;
|
||||
}
|
||||
|
||||
assert ( serverId <= 0xffffffff );
|
||||
|
||||
int status = this->lockAndReserveSpace ( 16u, reservoir );
|
||||
if ( status == ECA_NORMAL ) {
|
||||
comQueSend_copyIn ( this->bufs, reservoir, static_cast <ca_uint16_t> ( CA_PROTO_READ ) ); // cmd
|
||||
comQueSend_copyIn ( this->bufs, reservoir, static_cast <ca_uint16_t> ( 0u ) ); // postsize
|
||||
comQueSend_copyIn ( this->bufs, reservoir, static_cast <ca_uint16_t> ( type ) ); // dataType
|
||||
comQueSend_copyIn ( this->bufs, reservoir, static_cast <ca_uint16_t> ( nElem ) ); // count
|
||||
comQueSend_copyIn ( this->bufs, reservoir, static_cast <ca_uint32_t> ( serverId ) ); // cid
|
||||
comQueSend_copyIn ( this->bufs, reservoir, static_cast <ca_uint32_t> ( ioId ) ); // available
|
||||
this->mutex.unlock ();
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
int comQueSend::readNotifyRequest ( unsigned ioId, unsigned serverId, unsigned type, unsigned nElem )
|
||||
{
|
||||
bufferReservoir reservoir;
|
||||
|
||||
if ( nElem > 0xffff) {
|
||||
return ECA_BADCOUNT;
|
||||
}
|
||||
if ( type > 0xffff) {
|
||||
return ECA_BADTYPE;
|
||||
}
|
||||
|
||||
assert ( serverId <= 0xffffffff );
|
||||
|
||||
int status = this->lockAndReserveSpace ( 16u, reservoir );
|
||||
if ( status == ECA_NORMAL ) {
|
||||
comQueSend_copyIn ( this->bufs, reservoir, static_cast <ca_uint16_t> ( CA_PROTO_READ_NOTIFY ) ); // cmd
|
||||
comQueSend_copyIn ( this->bufs, reservoir, static_cast <ca_uint16_t> ( 0u ) ); // postsize
|
||||
comQueSend_copyIn ( this->bufs, reservoir, static_cast <ca_uint16_t> ( type ) ); // dataType
|
||||
comQueSend_copyIn ( this->bufs, reservoir, static_cast <ca_uint16_t> ( nElem ) ); // count
|
||||
comQueSend_copyIn ( this->bufs, reservoir, static_cast <ca_uint32_t> ( serverId ) ); // cid
|
||||
comQueSend_copyIn ( this->bufs, reservoir, static_cast <ca_uint32_t> ( ioId ) ); // available
|
||||
this->mutex.unlock ();
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
int comQueSend::createChannelRequest ( unsigned id, const char *pName, unsigned nameLength )
|
||||
{
|
||||
bufferReservoir reservoir;
|
||||
|
||||
unsigned postCnt = CA_MESSAGE_ALIGN ( nameLength );
|
||||
assert ( id <= 0xffffffff );
|
||||
assert ( postCnt <= 0xffff );
|
||||
|
||||
int status = this->lockAndReserveSpace ( postCnt + 16u, reservoir );
|
||||
if ( status == ECA_NORMAL ) {
|
||||
|
||||
comQueSend_copyIn ( this->bufs, reservoir, static_cast <ca_uint16_t> ( CA_PROTO_CLAIM_CIU ) ); // cmd
|
||||
comQueSend_copyIn ( this->bufs, reservoir, static_cast <ca_uint16_t> ( postCnt ) ); // postsize
|
||||
comQueSend_copyIn ( this->bufs, reservoir, static_cast <ca_uint16_t> ( 0u ) ); // dataType
|
||||
comQueSend_copyIn ( this->bufs, reservoir, static_cast <ca_uint16_t> ( 0u ) ); // count
|
||||
comQueSend_copyIn ( this->bufs, reservoir, static_cast <ca_uint32_t> ( id ) ); // cid
|
||||
//
|
||||
// The available field is used (abused)
|
||||
// here to communicate the minor version number
|
||||
// starting with CA 4.1.
|
||||
//
|
||||
comQueSend_copyIn ( this->bufs, reservoir, static_cast <ca_uint32_t> ( CA_MINOR_VERSION ) ); // available
|
||||
if ( nameLength ) {
|
||||
comQueSend_copyIn ( this->bufs, reservoir, pName, nameLength );
|
||||
}
|
||||
if ( postCnt > nameLength ) {
|
||||
comQueSend_copyIn ( this->bufs, reservoir, nillBytes, postCnt - nameLength );
|
||||
}
|
||||
this->mutex.unlock ();
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
int comQueSend::clearChannelRequest ( unsigned clientId, unsigned serverId )
|
||||
{
|
||||
bufferReservoir reservoir;
|
||||
|
||||
assert ( serverId <= 0xffffffff );
|
||||
assert ( clientId <= 0xffffffff );
|
||||
|
||||
int status = this->lockAndReserveSpace ( 16u, reservoir );
|
||||
if ( status == ECA_NORMAL ) {
|
||||
comQueSend_copyIn ( this->bufs, reservoir, static_cast <ca_uint16_t> ( CA_PROTO_CLEAR_CHANNEL ) ); // cmd
|
||||
comQueSend_copyIn ( this->bufs, reservoir, static_cast <ca_uint16_t> ( 0u ) ); // postsize
|
||||
comQueSend_copyIn ( this->bufs, reservoir, static_cast <ca_uint16_t> ( 0u ) ); // dataType
|
||||
comQueSend_copyIn ( this->bufs, reservoir, static_cast <ca_uint16_t> ( 0u ) ); // count
|
||||
comQueSend_copyIn ( this->bufs, reservoir, static_cast <ca_uint32_t> ( serverId ) ); // cid
|
||||
comQueSend_copyIn ( this->bufs, reservoir, static_cast <ca_uint32_t> ( clientId ) ); // available
|
||||
this->mutex.unlock ();
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
int comQueSend::subscriptionRequest ( unsigned ioId, unsigned serverId, unsigned type, unsigned nElem, unsigned mask )
|
||||
{
|
||||
bufferReservoir reservoir;
|
||||
|
||||
if ( nElem > 0xffff) {
|
||||
return ECA_BADCOUNT;
|
||||
}
|
||||
if ( type > 0xffff) {
|
||||
return ECA_BADTYPE;
|
||||
}
|
||||
assert ( serverId <= 0xffffffff );
|
||||
assert ( ioId <= 0xffffffff );
|
||||
|
||||
int status = this->lockAndReserveSpace ( 32u, reservoir );
|
||||
if ( status == ECA_NORMAL ) {
|
||||
|
||||
// header
|
||||
comQueSend_copyIn ( this->bufs, reservoir, static_cast <ca_uint16_t> ( CA_PROTO_EVENT_ADD ) ); // cmd
|
||||
comQueSend_copyIn ( this->bufs, reservoir, static_cast <ca_uint16_t> ( 16u ) ); // postsize
|
||||
comQueSend_copyIn ( this->bufs, reservoir, static_cast <ca_uint16_t> ( type ) ); // dataType
|
||||
comQueSend_copyIn ( this->bufs, reservoir, static_cast <ca_uint16_t> ( nElem ) ); // count
|
||||
comQueSend_copyIn ( this->bufs, reservoir, static_cast <ca_uint32_t> ( serverId ) ); // cid
|
||||
comQueSend_copyIn ( this->bufs, reservoir, static_cast <ca_uint32_t> ( ioId ) ); // available
|
||||
|
||||
// extension
|
||||
comQueSend_copyIn ( this->bufs, reservoir, static_cast < ca_float32_t > ( 0.0 ) ); // m_lval
|
||||
comQueSend_copyIn ( this->bufs, reservoir, static_cast < ca_float32_t > ( 0.0 ) ); // m_hval
|
||||
comQueSend_copyIn ( this->bufs, reservoir, static_cast < ca_float32_t > ( 0.0 ) ); // m_toval
|
||||
comQueSend_copyIn ( this->bufs, reservoir, static_cast < ca_uint16_t > ( mask ) ); // m_mask
|
||||
comQueSend_copyIn ( this->bufs, reservoir, static_cast < ca_uint16_t > ( 0u ) ); // m_pad
|
||||
|
||||
this->mutex.unlock ();
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
int comQueSend::subscriptionCancelRequest ( unsigned ioId, unsigned serverId, unsigned type, unsigned nElem )
|
||||
{
|
||||
bufferReservoir reservoir;
|
||||
|
||||
assert ( type <= 0xffff );
|
||||
assert ( nElem <= 0xffff );
|
||||
assert ( serverId <= 0xffffffff );
|
||||
assert ( ioId <= 0xffffffff );
|
||||
|
||||
int status = this->lockAndReserveSpace ( 16u, reservoir );
|
||||
if ( status == ECA_NORMAL ) {
|
||||
comQueSend_copyIn ( this->bufs, reservoir, static_cast <ca_uint16_t> ( CA_PROTO_EVENT_CANCEL ) ); // cmd
|
||||
comQueSend_copyIn ( this->bufs, reservoir, static_cast <ca_uint16_t> ( 0u ) ); // postsize
|
||||
comQueSend_copyIn ( this->bufs, reservoir, static_cast <ca_uint16_t> ( type ) ); // dataType
|
||||
comQueSend_copyIn ( this->bufs, reservoir, static_cast <ca_uint16_t> ( nElem ) ); // count
|
||||
comQueSend_copyIn ( this->bufs, reservoir, static_cast <ca_uint32_t> ( serverId ) ); // cid
|
||||
comQueSend_copyIn ( this->bufs, reservoir, static_cast <ca_uint32_t> ( ioId ) ); // available
|
||||
this->mutex.unlock ();
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
int comQueSend::disableFlowControlRequest ()
|
||||
{
|
||||
bufferReservoir reservoir;
|
||||
|
||||
int status = this->lockAndReserveSpace ( 16u, reservoir );
|
||||
if ( status == ECA_NORMAL ) {
|
||||
comQueSend_copyIn ( this->bufs, reservoir, static_cast <ca_uint16_t> ( CA_PROTO_EVENTS_ON ) ); // cmd
|
||||
comQueSend_copyIn ( this->bufs, reservoir, static_cast <ca_uint16_t> ( 0u ) ); // postsize
|
||||
comQueSend_copyIn ( this->bufs, reservoir, static_cast <ca_uint16_t> ( 0u ) ); // dataType
|
||||
comQueSend_copyIn ( this->bufs, reservoir, static_cast <ca_uint16_t> ( 0u ) ); // count
|
||||
comQueSend_copyIn ( this->bufs, reservoir, static_cast <ca_uint32_t> ( 0u ) ); // cid
|
||||
comQueSend_copyIn ( this->bufs, reservoir, static_cast <ca_uint32_t> ( 0u ) ); // available
|
||||
this->mutex.unlock ();
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
int comQueSend::enableFlowControlRequest ()
|
||||
{
|
||||
bufferReservoir reservoir;
|
||||
|
||||
int status = this->lockAndReserveSpace ( 16u, reservoir );
|
||||
if ( status == ECA_NORMAL ) {
|
||||
comQueSend_copyIn ( this->bufs, reservoir, static_cast <ca_uint16_t> ( CA_PROTO_EVENTS_OFF ) ); // cmd
|
||||
comQueSend_copyIn ( this->bufs, reservoir, static_cast <ca_uint16_t> ( 0u ) ); // postsize
|
||||
comQueSend_copyIn ( this->bufs, reservoir, static_cast <ca_uint16_t> ( 0u ) ); // dataType
|
||||
comQueSend_copyIn ( this->bufs, reservoir, static_cast <ca_uint16_t> ( 0u ) ); // count
|
||||
comQueSend_copyIn ( this->bufs, reservoir, static_cast <ca_uint32_t> ( 0u ) ); // cid
|
||||
comQueSend_copyIn ( this->bufs, reservoir, static_cast <ca_uint32_t> ( 0u ) ); // available
|
||||
this->mutex.unlock ();
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
int comQueSend::noopRequest ()
|
||||
{
|
||||
bufferReservoir reservoir;
|
||||
|
||||
int status = this->lockAndReserveSpace ( 16u, reservoir );
|
||||
if ( status == ECA_NORMAL ) {
|
||||
comQueSend_copyIn ( this->bufs, reservoir, static_cast <ca_uint16_t> ( CA_PROTO_NOOP ) ); // cmd
|
||||
comQueSend_copyIn ( this->bufs, reservoir, static_cast <ca_uint16_t> ( 0u ) ); // postsize
|
||||
comQueSend_copyIn ( this->bufs, reservoir, static_cast <ca_uint16_t> ( 0u ) ); // dataType
|
||||
comQueSend_copyIn ( this->bufs, reservoir, static_cast <ca_uint16_t> ( 0u ) ); // count
|
||||
comQueSend_copyIn ( this->bufs, reservoir, static_cast <ca_uint32_t> ( 0u ) ); // cid
|
||||
comQueSend_copyIn ( this->bufs, reservoir, static_cast <ca_uint32_t> ( 0u ) ); // available
|
||||
this->mutex.unlock ();
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
int comQueSend::echoRequest ()
|
||||
{
|
||||
bufferReservoir reservoir;
|
||||
|
||||
int status = this->lockAndReserveSpace ( 16u, reservoir );
|
||||
if ( status == ECA_NORMAL ) {
|
||||
comQueSend_copyIn ( this->bufs, reservoir, static_cast <ca_uint16_t> ( CA_PROTO_ECHO ) ); // cmd
|
||||
comQueSend_copyIn ( this->bufs, reservoir, static_cast <ca_uint16_t> ( 0u ) ); // postsize
|
||||
comQueSend_copyIn ( this->bufs, reservoir, static_cast <ca_uint16_t> ( 0u ) ); // dataType
|
||||
comQueSend_copyIn ( this->bufs, reservoir, static_cast <ca_uint16_t> ( 0u ) ); // count
|
||||
comQueSend_copyIn ( this->bufs, reservoir, static_cast <ca_uint32_t> ( 0u ) ); // cid
|
||||
comQueSend_copyIn ( this->bufs, reservoir, static_cast <ca_uint32_t> ( 0u ) ); // available
|
||||
this->mutex.unlock ();
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
int comQueSend::hostNameSetRequest ( const char *pName )
|
||||
{
|
||||
bufferReservoir reservoir;
|
||||
unsigned size = strlen ( pName ) + 1u;
|
||||
unsigned postSize = CA_MESSAGE_ALIGN ( size );
|
||||
assert ( postSize < 0xffff );
|
||||
|
||||
int status = this->lockAndReserveSpace ( postSize + 16u, reservoir );
|
||||
if ( status == ECA_NORMAL ) {
|
||||
comQueSend_copyIn ( this->bufs, reservoir, static_cast <ca_uint16_t> ( CA_PROTO_HOST_NAME ) ); // cmd
|
||||
comQueSend_copyIn ( this->bufs, reservoir, static_cast <ca_uint16_t> ( postSize ) ); // postsize
|
||||
comQueSend_copyIn ( this->bufs, reservoir, static_cast <ca_uint16_t> ( 0u ) ); // dataType
|
||||
comQueSend_copyIn ( this->bufs, reservoir, static_cast <ca_uint16_t> ( 0u ) ); // count
|
||||
comQueSend_copyIn ( this->bufs, reservoir, static_cast <ca_uint32_t> ( 0u ) ); // cid
|
||||
comQueSend_copyIn ( this->bufs, reservoir, static_cast <ca_uint32_t> ( 0u ) ); // available
|
||||
|
||||
comQueSend_copyIn ( this->bufs, reservoir, pName, size );
|
||||
comQueSend_copyIn ( this->bufs, reservoir, nillBytes, postSize - size );
|
||||
this->mutex.unlock ();
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
int comQueSend::userNameSetRequest ( const char *pName )
|
||||
{
|
||||
bufferReservoir reservoir;
|
||||
unsigned size = strlen ( pName ) + 1u;
|
||||
unsigned postSize = CA_MESSAGE_ALIGN ( size );
|
||||
assert ( postSize < 0xffff );
|
||||
|
||||
int status = this->lockAndReserveSpace ( postSize + 16u, reservoir );
|
||||
if ( status == ECA_NORMAL ) {
|
||||
comQueSend_copyIn ( this->bufs, reservoir, static_cast <ca_uint16_t> ( CA_PROTO_CLIENT_NAME ) ); // cmd
|
||||
comQueSend_copyIn ( this->bufs, reservoir, static_cast <ca_uint16_t> ( postSize ) ); // postsize
|
||||
comQueSend_copyIn ( this->bufs, reservoir, static_cast <ca_uint16_t> ( 0u ) ); // dataType
|
||||
comQueSend_copyIn ( this->bufs, reservoir, static_cast <ca_uint16_t> ( 0u ) ); // count
|
||||
comQueSend_copyIn ( this->bufs, reservoir, static_cast <ca_uint32_t> ( 0u ) ); // cid
|
||||
comQueSend_copyIn ( this->bufs, reservoir, static_cast <ca_uint32_t> ( 0u ) ); // available
|
||||
|
||||
comQueSend_copyIn ( this->bufs, reservoir, pName, size );
|
||||
comQueSend_copyIn ( this->bufs, reservoir, nillBytes, postSize - size );
|
||||
this->mutex.unlock ();
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* tcpiiu::pushStreamMsg ()
|
||||
*/
|
||||
int tcpiiu::pushStreamMsg ( const caHdr &hdr, const void *pext, unsigned extsize )
|
||||
{
|
||||
unsigned alignedExtSize;
|
||||
bool status;
|
||||
msgDescriptor msgs[3];
|
||||
caHdr msgHdr = hdr;
|
||||
|
||||
if ( extsize > 0xffff - 7 ) {
|
||||
return ECA_TOLARGE;
|
||||
}
|
||||
|
||||
alignedExtSize = CA_MESSAGE_ALIGN ( extsize );
|
||||
msgHdr.m_postsize = htons ( alignedExtSize );
|
||||
|
||||
debugPrintf ( (
|
||||
"CAC: Request => cmmd=%x cid=0x%x type=%x count=%x postsize=%x\n",
|
||||
hdr.m_cmmd, hdr.m_cid, hdr.m_dataType,
|
||||
hdr.m_count, hdr.m_postsize ) );
|
||||
|
||||
msgs[0].pBuf = &msgHdr;
|
||||
msgs[0].nBytes = sizeof ( msgHdr );
|
||||
msgs[1].pBuf = pext;
|
||||
msgs[1].nBytes = extsize;
|
||||
if ( alignedExtSize > extsize ) {
|
||||
unsigned diff = alignedExtSize - extsize;
|
||||
assert ( diff <= sizeof ( nullBuff ) );
|
||||
msgs[2].pBuf = nullBuff;
|
||||
msgs[2].nBytes = diff;
|
||||
status = this->copyInBytes ( msgs, 3u );
|
||||
}
|
||||
else {
|
||||
status = this->copyInBytes ( msgs, 2u );
|
||||
}
|
||||
|
||||
if ( status ) {
|
||||
return ECA_NORMAL;
|
||||
}
|
||||
else {
|
||||
this->shutdown ();
|
||||
return ECA_ALLOCMEM;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* tcpiiu::pushStreamMsg ()
|
||||
*/
|
||||
int tcpiiu::pushStreamMsg ( const caHdr &hdr )
|
||||
{
|
||||
caHdr msgHdr = hdr;
|
||||
msgHdr.m_postsize = htons ( 0 );
|
||||
|
||||
debugPrintf ( (
|
||||
"CAC: Request => cmmd=%x cid=0x%x type=%x count=%x postsize=%x\n",
|
||||
hdr.m_cmmd, hdr.m_cid, hdr.m_dataType,
|
||||
hdr.m_count, hdr.m_postsize ) );
|
||||
|
||||
bool status = this->copyIn ( msgHdr );
|
||||
if ( status ) {
|
||||
return ECA_NORMAL;
|
||||
}
|
||||
else {
|
||||
this->shutdown ();
|
||||
return ECA_ALLOCMEM;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,25 @@
|
||||
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
*
|
||||
* L O S A L A M O S
|
||||
* Los Alamos National Laboratory
|
||||
* Los Alamos, New Mexico 87545
|
||||
*
|
||||
* Copyright, 2000, The Regents of the University of California.
|
||||
*
|
||||
*
|
||||
* Author Jeffrey O. Hill
|
||||
* johill@lanl.gov
|
||||
* 505 665 1831
|
||||
*/
|
||||
|
||||
#ifndef comQueSend_ILh
|
||||
#define comQueSend_ILh
|
||||
|
||||
|
||||
|
||||
|
||||
#endif // comQueSend_ILh
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
/* $Id$ */
|
||||
/*
|
||||
*
|
||||
* L O S A L A M O S
|
||||
* Los Alamos National Laboratory
|
||||
* Los Alamos, New Mexico 87545
|
||||
*
|
||||
* Copyright, 1986, The Regents of the University of California.
|
||||
*
|
||||
* Author: Jeff Hill
|
||||
*/
|
||||
|
||||
#include "iocinf.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
#define LOGRETRYINTERVAL logRetryInterval(__FILE__, __LINE__);
|
||||
LOCAL void logRetryInterval (pcac, char *pFN, unsigned lineno);
|
||||
#else
|
||||
#define LOGRETRYINTERVAL
|
||||
#endif
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
*
|
||||
* L O S A L A M O S
|
||||
* Los Alamos National Laboratory
|
||||
* Los Alamos, New Mexico 87545
|
||||
*
|
||||
* Copyright, 1986, The Regents of the University of California.
|
||||
*
|
||||
*
|
||||
* Author Jeffrey O. Hill
|
||||
* johill@lanl.gov
|
||||
*/
|
||||
|
||||
#include "iocinf.h"
|
||||
|
||||
hostNameCache::hostNameCache ( const osiSockAddr &addr, ipAddrToAsciiEngine &engine ) :
|
||||
ipAddrToAsciiAsynchronous ( addr ),
|
||||
pHostName ( 0u )
|
||||
{
|
||||
this->ioInitiate ( engine );
|
||||
}
|
||||
|
||||
hostNameCache::~hostNameCache ()
|
||||
{
|
||||
if ( this->pHostName ) {
|
||||
delete [] this->pHostName;
|
||||
}
|
||||
}
|
||||
|
||||
void hostNameCache::ioCompletionNotify ( const char *pHostNameIn )
|
||||
{
|
||||
if ( ! this->pHostName ) {
|
||||
unsigned size = strlen ( pHostNameIn ) + 1u;
|
||||
char *pTmp = new char [size];
|
||||
if ( ! pTmp ) {
|
||||
// we fail over to using the IP address for the name
|
||||
return;
|
||||
}
|
||||
strcpy ( pTmp, pHostNameIn );
|
||||
this->pHostName = pTmp;
|
||||
}
|
||||
}
|
||||
|
||||
void hostNameCache::hostName ( char *pBuf, unsigned bufSize ) const
|
||||
{
|
||||
if ( this->pHostName ) {
|
||||
strncpy ( pBuf, this->pHostName, bufSize);
|
||||
}
|
||||
else {
|
||||
osiSockAddr addr = this->address();
|
||||
sockAddrToDottedA ( &addr.sa, pBuf, bufSize );
|
||||
}
|
||||
pBuf [ bufSize - 1u ] = '\0';
|
||||
}
|
||||
+10
-10
@@ -116,8 +116,8 @@ epicsShareFunc void epicsShareAPI setPortAndRemoveDuplicates
|
||||
if (pNode->addr.ia.sin_addr.s_addr == pTmpNode->addr.ia.sin_addr.s_addr &&
|
||||
pNode->addr.ia.sin_port == pTmpNode->addr.ia.sin_port) {
|
||||
char buf[64];
|
||||
ipAddrToA (&pNode->addr.ia, buf, sizeof(buf));
|
||||
ca_printf ("Warning: Duplicate EPICS CA Address list entry \"%s\" discarded\n", buf);
|
||||
ipAddrToA ( &pNode->addr.ia, buf, sizeof (buf) );
|
||||
ca_printf ( "Warning: Duplicate EPICS CA Address list entry \"%s\" discarded\n", buf );
|
||||
free (pNode);
|
||||
pNode = NULL;
|
||||
break;
|
||||
@@ -139,7 +139,7 @@ epicsShareFunc void epicsShareAPI setPortAndRemoveDuplicates
|
||||
* configureChannelAccessAddressList ()
|
||||
*/
|
||||
epicsShareFunc void epicsShareAPI configureChannelAccessAddressList
|
||||
(ELLLIST *pList, SOCKET sock, unsigned short port)
|
||||
( ELLLIST *pList, SOCKET sock, unsigned short port )
|
||||
{
|
||||
ELLLIST tmpList;
|
||||
char *pstr;
|
||||
@@ -149,7 +149,7 @@ epicsShareFunc void epicsShareAPI configureChannelAccessAddressList
|
||||
/*
|
||||
* dont load the list twice
|
||||
*/
|
||||
assert ( ellCount(pList) == 0 );
|
||||
assert ( ellCount (pList) == 0 );
|
||||
|
||||
ellInit ( &tmpList );
|
||||
|
||||
@@ -202,16 +202,16 @@ epicsShareFunc void epicsShareAPI configureChannelAccessAddressList
|
||||
/*
|
||||
* printChannelAccessAddressList ()
|
||||
*/
|
||||
epicsShareFunc void epicsShareAPI printChannelAccessAddressList (const ELLLIST *pList)
|
||||
epicsShareFunc void epicsShareAPI printChannelAccessAddressList ( const ELLLIST *pList )
|
||||
{
|
||||
osiSockAddrNode *pNode;
|
||||
|
||||
printf ("Channel Access Address List\n");
|
||||
pNode = (osiSockAddrNode *) ellFirst (pList);
|
||||
printf ( "Channel Access Address List\n" );
|
||||
pNode = (osiSockAddrNode *) ellFirst ( pList );
|
||||
while (pNode) {
|
||||
char buf[64];
|
||||
ipAddrToA (&pNode->addr.ia, buf, sizeof(buf));
|
||||
printf ("%s\n", buf);
|
||||
pNode = (osiSockAddrNode *) ellNext (&pNode->node);
|
||||
ipAddrToA ( &pNode->addr.ia, buf, sizeof ( buf ) );
|
||||
printf ( "%s\n", buf );
|
||||
pNode = (osiSockAddrNode *) ellNext ( &pNode->node );
|
||||
}
|
||||
}
|
||||
|
||||
+550
-231
File diff suppressed because it is too large
Load Diff
@@ -20,10 +20,25 @@ localHostName localHostNameAtLoadTime;
|
||||
|
||||
localHostName::localHostName ()
|
||||
{
|
||||
int status = gethostname ( this->cache, sizeof ( this->cache ) );
|
||||
int status = osiSockAttach ();
|
||||
if ( status ) {
|
||||
strncpy ( this->cache, "<unknown host>", sizeof ( this->cache ) );
|
||||
localHostName::cache [ sizeof ( this->cache ) - 1u ] = '\0';
|
||||
this->attachedToSockLib = true;
|
||||
int status = gethostname ( this->cache, sizeof ( this->cache ) );
|
||||
if ( status ) {
|
||||
strncpy ( this->cache, "<unknown host>", sizeof ( this->cache ) );
|
||||
localHostName::cache [ sizeof ( this->cache ) - 1u ] = '\0';
|
||||
}
|
||||
this->length = strlen ( this->cache );
|
||||
}
|
||||
else {
|
||||
this->attachedToSockLib = false;
|
||||
strncpy ( this->cache, "<unknown host>", sizeof ( this->cache ) );
|
||||
}
|
||||
}
|
||||
|
||||
localHostName::~localHostName ()
|
||||
{
|
||||
if ( this->attachedToSockLib ) {
|
||||
osiSockRelease ();
|
||||
}
|
||||
this->length = strlen ( this->cache );
|
||||
}
|
||||
|
||||
@@ -13,10 +13,12 @@
|
||||
class localHostName {
|
||||
public:
|
||||
localHostName ();
|
||||
~localHostName ();
|
||||
const char * pointer () const;
|
||||
void copy ( char *pBuf, unsigned bufLength ) const;
|
||||
unsigned stringLength () const;
|
||||
private:
|
||||
bool attachedToSockLib;
|
||||
unsigned length;
|
||||
char cache [128];
|
||||
};
|
||||
|
||||
+442
-558
File diff suppressed because it is too large
Load Diff
@@ -30,7 +30,136 @@ inline void nciu::operator delete ( void *pCadaver, size_t size )
|
||||
nciu::freeList.release ( pCadaver, size );
|
||||
}
|
||||
|
||||
inline void nciu::lock () const
|
||||
{
|
||||
this->cacCtx.nciuPrivate::mutex.lock ();
|
||||
}
|
||||
|
||||
inline void nciu::unlock () const
|
||||
{
|
||||
this->cacCtx.nciuPrivate::mutex.unlock ();
|
||||
}
|
||||
|
||||
inline bool nciu::fullyConstructed () const
|
||||
{
|
||||
return this->f_fullyConstructed;
|
||||
}
|
||||
|
||||
inline bool nciu::identifierEquivelence ( unsigned idToMatch )
|
||||
{
|
||||
return idToMatch == this->id;
|
||||
}
|
||||
|
||||
inline void nciu::resetRetryCount ()
|
||||
{
|
||||
this->retry = 0u;
|
||||
}
|
||||
|
||||
inline void nciu::accessRightsStateChange ( const caar &arIn )
|
||||
{
|
||||
this->ar = ar;
|
||||
this->accessRightsNotify ( this->ar );
|
||||
}
|
||||
|
||||
inline unsigned nciu::getSID () const
|
||||
{
|
||||
return this->sid;
|
||||
}
|
||||
|
||||
inline unsigned nciu::getRetrySeqNo () const
|
||||
{
|
||||
return this->retrySeqNo;
|
||||
}
|
||||
|
||||
inline void nciu::lockPIIU () const
|
||||
{
|
||||
this->lock ();
|
||||
assert ( this->ptrLockCount < USHRT_MAX );
|
||||
this->ptrLockCount++;
|
||||
this->unlock ();
|
||||
}
|
||||
|
||||
inline void nciu::unlockPIIU () const
|
||||
{
|
||||
bool signalNeeded;
|
||||
|
||||
this->lock ();
|
||||
assert ( this->ptrLockCount > 0 );
|
||||
this->ptrLockCount--;
|
||||
if ( this->ptrLockCount == 0u && this->ptrUnlockWaitCount > 0u ) {
|
||||
this->ptrUnlockWaitCount--;
|
||||
signalNeeded = true;
|
||||
}
|
||||
else {
|
||||
signalNeeded = false;
|
||||
}
|
||||
this->unlock ();
|
||||
|
||||
if ( signalNeeded ) {
|
||||
this->cacCtx.nciuPrivate::ptrLockReleaseWakeup.signal ();
|
||||
}
|
||||
}
|
||||
|
||||
inline void nciu::subscriptionCancelMsg ( ca_uint32_t clientId )
|
||||
{
|
||||
this->lockPIIU ();
|
||||
|
||||
if ( this->piiu ) {
|
||||
this->piiu->subscriptionCancelRequest ( clientId, this->sid, this->typeCode, this->count );
|
||||
}
|
||||
|
||||
this->unlockPIIU ();
|
||||
}
|
||||
|
||||
inline void nciu::connect ( tcpiiu &iiu )
|
||||
{
|
||||
this->connect ( iiu, this->typeCode, this->count, this->sid );
|
||||
}
|
||||
|
||||
inline void nciu::searchReplySetUp ( unsigned sidIn,
|
||||
unsigned typeIn, unsigned long countIn )
|
||||
{
|
||||
this->lock ();
|
||||
|
||||
this->typeCode = typeIn;
|
||||
this->count = countIn;
|
||||
this->sid = sidIn;
|
||||
this->ar.read_access = true;
|
||||
this->ar.write_access = true;
|
||||
|
||||
this->unlock ();
|
||||
}
|
||||
|
||||
inline bool nciu::connected () const
|
||||
{
|
||||
return this->f_connected;
|
||||
}
|
||||
|
||||
inline bool nciu::connectionInProgress ( const osiSockAddr &addrIn )
|
||||
{
|
||||
bool status;
|
||||
|
||||
this->lockPIIU ();
|
||||
|
||||
if ( this->piiu ) {
|
||||
status = this->piiu->connectionInProgress ( this->pNameStr, addrIn );
|
||||
}
|
||||
else {
|
||||
status = false;
|
||||
}
|
||||
|
||||
this->unlockPIIU ();
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
inline void nciu::ioInstall ( class baseNMIU &nmiu )
|
||||
{
|
||||
this->cacCtx.ioInstall ( *this, nmiu );
|
||||
}
|
||||
|
||||
inline void nciu::ioDestroy ( unsigned id )
|
||||
{
|
||||
this->cacCtx.ioDestroy ( id );
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
*/
|
||||
|
||||
#include "iocinf.h"
|
||||
#include "netReadCopyIO_IL.h"
|
||||
#include "nciu_IL.h"
|
||||
|
||||
tsFreeList < class netReadCopyIO, 1024 > netReadCopyIO::freeList;
|
||||
|
||||
@@ -24,12 +26,13 @@ netReadCopyIO::netReadCopyIO ( nciu &chanIn, unsigned typeIn, unsigned long coun
|
||||
|
||||
netReadCopyIO::~netReadCopyIO ()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void netReadCopyIO::disconnect ( const char *pHostName )
|
||||
{
|
||||
this->exceptionNotify ( ECA_DISCONN, pHostName );
|
||||
delete this;
|
||||
this->baseNMIU::destroy ();
|
||||
}
|
||||
|
||||
void netReadCopyIO::completionNotify ()
|
||||
@@ -48,7 +51,7 @@ void netReadCopyIO::completionNotify ( unsigned typeIn,
|
||||
memcpy ( this->pValue, pDataIn,
|
||||
dbr_size_n ( typeIn, countIn ) );
|
||||
# endif
|
||||
chan.decrementOutstandingIO (this->seqNumber);
|
||||
this->chan.decrementOutstandingIO (this->seqNumber);
|
||||
}
|
||||
else {
|
||||
this->exceptionNotify ( ECA_INTERNAL, "bad data type in message" );
|
||||
@@ -67,13 +70,3 @@ void netReadCopyIO::exceptionNotify ( int status,
|
||||
"%s type=%d count=%ld\n",
|
||||
pContextIn, typeIn, countIn);
|
||||
}
|
||||
|
||||
void * netReadCopyIO::operator new ( size_t size )
|
||||
{
|
||||
return netReadCopyIO::freeList.allocate ( size );
|
||||
}
|
||||
|
||||
void netReadCopyIO::operator delete ( void *pCadaver, size_t size )
|
||||
{
|
||||
netReadCopyIO::freeList.release ( pCadaver, size );
|
||||
}
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
*
|
||||
* L O S A L A M O S
|
||||
* Los Alamos National Laboratory
|
||||
* Los Alamos, New Mexico 87545
|
||||
*
|
||||
* Copyright, 1986, The Regents of the University of California.
|
||||
*
|
||||
*
|
||||
* Author Jeffrey O. Hill
|
||||
* johill@lanl.gov
|
||||
* 505 665 1831
|
||||
*/
|
||||
|
||||
#ifndef netReadCopyIO_ILh
|
||||
#define netReadCopyIO_ILh
|
||||
|
||||
//
|
||||
// we need to be careful about exporting a raw IO
|
||||
// pointer because the IO object may be deleted
|
||||
// at any time when the channel disconnects or the
|
||||
// IO completes
|
||||
//
|
||||
inline bool netReadCopyIO::factory ( nciu &chan, unsigned type,
|
||||
unsigned long count, void *pValue, unsigned seqNumber, unsigned &id )
|
||||
{
|
||||
netReadCopyIO *pIO = new netReadCopyIO ( chan,
|
||||
type, count, pValue, seqNumber );
|
||||
if ( pIO ) {
|
||||
id = pIO->getId ();
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
inline void * netReadCopyIO::operator new ( size_t size )
|
||||
{
|
||||
return netReadCopyIO::freeList.allocate ( size );
|
||||
}
|
||||
|
||||
inline void netReadCopyIO::operator delete ( void *pCadaver, size_t size )
|
||||
{
|
||||
netReadCopyIO::freeList.release ( pCadaver, size );
|
||||
}
|
||||
|
||||
|
||||
#endif // netReadCopyIO_ILh
|
||||
@@ -22,17 +22,18 @@ netReadNotifyIO::netReadNotifyIO ( nciu &chan, cacNotify ¬ifyIn ) :
|
||||
|
||||
netReadNotifyIO::~netReadNotifyIO ()
|
||||
{
|
||||
// private NOOP forces pool allocation
|
||||
}
|
||||
|
||||
void netReadNotifyIO::destroy ()
|
||||
{
|
||||
delete this;
|
||||
this->baseNMIU::destroy ();
|
||||
}
|
||||
|
||||
void netReadNotifyIO::disconnect ( const char *pHostName )
|
||||
{
|
||||
this->cacNotifyIO::exceptionNotify ( ECA_DISCONN, pHostName );
|
||||
delete this;
|
||||
this->baseNMIU::destroy ();
|
||||
}
|
||||
|
||||
void netReadNotifyIO::completionNotify ()
|
||||
|
||||
@@ -15,13 +15,35 @@
|
||||
* 505 665 1831
|
||||
*/
|
||||
|
||||
inline void * netReadNotifyIO::operator new (size_t size)
|
||||
#ifndef netReadNotifyIO_ILh
|
||||
#define netReadNotifyIO_ILh
|
||||
|
||||
inline void * netReadNotifyIO::operator new ( size_t size )
|
||||
{
|
||||
return netReadNotifyIO::freeList.allocate (size);
|
||||
return netReadNotifyIO::freeList.allocate ( size );
|
||||
}
|
||||
|
||||
inline void netReadNotifyIO::operator delete (void *pCadaver, size_t size)
|
||||
inline void netReadNotifyIO::operator delete ( void *pCadaver, size_t size )
|
||||
{
|
||||
netReadNotifyIO::freeList.release (pCadaver,size);
|
||||
netReadNotifyIO::freeList.release ( pCadaver, size );
|
||||
}
|
||||
|
||||
//
|
||||
// we need to be careful about exporting a raw IO
|
||||
// pointer because the IO object may be deleted
|
||||
// at any time when the channel disconnects or the
|
||||
// IO completes
|
||||
//
|
||||
inline bool netReadNotifyIO::factory ( nciu &chan, cacNotify ¬ify, ca_uint32_t &id )
|
||||
{
|
||||
netReadNotifyIO *pIO = new netReadNotifyIO ( chan, notify );
|
||||
if ( pIO ) {
|
||||
id = pIO->getId ();
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // netReadNotifyIO_ILh
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
|
||||
#include "iocinf.h"
|
||||
#include "netSubscription_IL.h"
|
||||
#include "nciu_IL.h"
|
||||
|
||||
tsFreeList < class netSubscription, 1024 > netSubscription::freeList;
|
||||
|
||||
@@ -20,41 +21,22 @@ netSubscription::netSubscription ( nciu &chan, chtype typeIn, unsigned long coun
|
||||
cacNotifyIO (notifyIn), baseNMIU (chan),
|
||||
type (typeIn), count (countIn), mask (maskIn)
|
||||
{
|
||||
this->subscriptionMsg ();
|
||||
}
|
||||
|
||||
netSubscription::~netSubscription ()
|
||||
{
|
||||
if ( this->chan.connected () ) {
|
||||
caHdr hdr;
|
||||
ca_uint16_t type_16, count_16;
|
||||
|
||||
type_16 = (ca_uint16_t) this->chan.nativeType ();
|
||||
if ( this->chan.nativeElementCount () > 0xffff ) {
|
||||
count_16 = 0xffff;
|
||||
}
|
||||
else {
|
||||
count_16 = (ca_uint16_t) this->chan.nativeElementCount ();
|
||||
}
|
||||
|
||||
hdr.m_cmmd = htons (CA_PROTO_EVENT_CANCEL);
|
||||
hdr.m_available = this->id;
|
||||
hdr.m_dataType = htons ( type_16 );
|
||||
hdr.m_count = htons ( count_16 );
|
||||
hdr.m_cid = this->chan.sid;
|
||||
hdr.m_postsize = 0;
|
||||
|
||||
this->chan.piiu->pushStreamMsg (&hdr, NULL, true);
|
||||
}
|
||||
this->chan.subscriptionCancelMsg ( this->getId () );
|
||||
}
|
||||
|
||||
void netSubscription::destroy()
|
||||
{
|
||||
delete this;
|
||||
this->baseNMIU::destroy ();
|
||||
}
|
||||
|
||||
int netSubscription::subscriptionMsg ()
|
||||
{
|
||||
return this->chan.subscriptionMsg ( this->id, this->type,
|
||||
return this->chan.subscriptionMsg ( this->getId (), this->type,
|
||||
this->count, this->mask );
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,9 @@
|
||||
* 505 665 1831
|
||||
*/
|
||||
|
||||
#ifndef netSubscription_ILh
|
||||
#define netSubscription_ILh
|
||||
|
||||
|
||||
inline void * netSubscription::operator new (size_t size)
|
||||
{
|
||||
@@ -25,3 +28,26 @@ inline void netSubscription::operator delete (void *pCadaver, size_t size)
|
||||
{
|
||||
netSubscription::freeList.release (pCadaver,size);
|
||||
}
|
||||
|
||||
//
|
||||
// we need to be careful about exporting a raw IO
|
||||
// pointer because the IO object may be deleted
|
||||
// at any time when the channel disconnects or the
|
||||
// IO completes
|
||||
//
|
||||
inline bool netSubscription::factory ( nciu &chan, chtype type, unsigned long count,
|
||||
unsigned short mask, cacNotify ¬ify, unsigned &id )
|
||||
{
|
||||
netSubscription *pIO = new netSubscription ( chan, type, count, mask, notify );
|
||||
if ( pIO ) {
|
||||
id = pIO->getId ();
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // netSubscription_ILh
|
||||
|
||||
|
||||
|
||||
@@ -22,17 +22,18 @@ netWriteNotifyIO::netWriteNotifyIO (nciu &chan, cacNotify ¬ifyIn) :
|
||||
|
||||
netWriteNotifyIO::~netWriteNotifyIO ()
|
||||
{
|
||||
// private NOOP forces pool allocation
|
||||
}
|
||||
|
||||
void netWriteNotifyIO::destroy ()
|
||||
{
|
||||
delete this;
|
||||
this->baseNMIU::destroy ();
|
||||
}
|
||||
|
||||
void netWriteNotifyIO::disconnect ( const char *pHostName )
|
||||
{
|
||||
this->exceptionNotify (ECA_DISCONN, pHostName);
|
||||
delete this;
|
||||
this->baseNMIU::destroy ();
|
||||
}
|
||||
|
||||
void netWriteNotifyIO::completionNotify ()
|
||||
|
||||
@@ -28,3 +28,22 @@ inline void netWriteNotifyIO::operator delete ( void *pCadaver, size_t size )
|
||||
netWriteNotifyIO::freeList.release ( pCadaver, size );
|
||||
}
|
||||
|
||||
//
|
||||
// we need to be careful about exporting a raw IO
|
||||
// pointer because the IO object may be deleted
|
||||
// at any time when the channel disconnects or the
|
||||
// IO completes
|
||||
//
|
||||
inline bool netWriteNotifyIO::factory ( nciu &chan, cacNotify ¬ify, ca_uint32_t &id )
|
||||
{
|
||||
netWriteNotifyIO *pIO = new netWriteNotifyIO ( chan, notify );
|
||||
if ( pIO ) {
|
||||
id = pIO->getId ();
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
+201
-21
@@ -11,25 +11,13 @@
|
||||
*/
|
||||
|
||||
#include "iocinf.h"
|
||||
#include "nciu_IL.h"
|
||||
#include "claimMsgCache_IL.h"
|
||||
|
||||
/*
|
||||
* constructNIIU ()
|
||||
*/
|
||||
netiiu::netiiu (cac *pcac) : baseIIU (pcac)
|
||||
{
|
||||
ellInit (&this->chidList);
|
||||
}
|
||||
|
||||
/*
|
||||
* netiiu::~netiiu ()
|
||||
*/
|
||||
netiiu::~netiiu ()
|
||||
{
|
||||
}
|
||||
|
||||
void netiiu::show ( unsigned /* level */ ) const
|
||||
{
|
||||
this->pcas->lock ();
|
||||
this->lock ();
|
||||
|
||||
tsDLIterConstBD <nciu> pChan ( this->chidList.first () );
|
||||
while ( pChan.valid () ) {
|
||||
@@ -41,25 +29,217 @@ void netiiu::show ( unsigned /* level */ ) const
|
||||
pChan->nativeElementCount (), hostName );
|
||||
switch ( pChan->state () ) {
|
||||
case cs_never_conn:
|
||||
printf ("never connected to an IOC");
|
||||
printf ( "never connected to an IOC" );
|
||||
break;
|
||||
case cs_prev_conn:
|
||||
printf ("disconnected from IOC");
|
||||
printf ( "disconnected from IOC" );
|
||||
break;
|
||||
case cs_conn:
|
||||
printf ("connected to an IOC");
|
||||
printf ( "connected to an IOC" );
|
||||
break;
|
||||
case cs_closed:
|
||||
printf ("invalid channel");
|
||||
printf ( "invalid channel" );
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
printf("\n");
|
||||
printf ( "\n" );
|
||||
}
|
||||
|
||||
this->pcas->unlock ();
|
||||
this->unlock ();
|
||||
|
||||
}
|
||||
|
||||
unsigned netiiu::channelCount () const
|
||||
{
|
||||
return this->chidList.count ();
|
||||
}
|
||||
|
||||
void netiiu::lock () const
|
||||
{
|
||||
this->mutex.lock ();
|
||||
}
|
||||
|
||||
void netiiu::unlock () const
|
||||
{
|
||||
this->mutex.unlock ();
|
||||
}
|
||||
|
||||
void netiiu::detachAllChan ()
|
||||
{
|
||||
this->lock ();
|
||||
tsDLIterBD <nciu> chan ( this->chidList.first () );
|
||||
while ( chan.valid () ) {
|
||||
tsDLIterBD <nciu> next = chan.itemAfter ();
|
||||
chan->detachChanFromIIU ();
|
||||
chan = next;
|
||||
}
|
||||
this->unlock ();
|
||||
}
|
||||
|
||||
void netiiu::disconnectAllChan ()
|
||||
{
|
||||
this->lock ();
|
||||
tsDLIterBD <nciu> chan ( this->chidList.first () );
|
||||
while ( chan.valid () ) {
|
||||
tsDLIterBD <nciu> next = chan.itemAfter ();
|
||||
chan->disconnect ();
|
||||
chan = next;
|
||||
}
|
||||
this->unlock ();
|
||||
}
|
||||
|
||||
void netiiu::connectTimeoutNotify ()
|
||||
{
|
||||
this->lock ();
|
||||
tsDLIterBD <nciu> chan ( this->chidList.first () );
|
||||
while ( chan.valid () ) {
|
||||
chan->connectTimeoutNotify ();
|
||||
chan++;
|
||||
}
|
||||
this->unlock ();
|
||||
}
|
||||
|
||||
void netiiu::resetChannelRetryCounts ()
|
||||
{
|
||||
this->lock ();
|
||||
tsDLIterBD <nciu> chan ( this->chidList.first () );
|
||||
while ( chan.valid () ) {
|
||||
chan->resetRetryCount ();
|
||||
chan++;
|
||||
}
|
||||
this->unlock ();
|
||||
}
|
||||
|
||||
bool netiiu::searchMsg ( unsigned short retrySeqNumber, unsigned &retryNoForThisChannel )
|
||||
{
|
||||
bool status;
|
||||
|
||||
this->lock ();
|
||||
|
||||
tsDLIterBD <nciu> chan = this->chidList.first ();
|
||||
if ( chan.valid () ) {
|
||||
status = chan->searchMsg ( retrySeqNumber, retryNoForThisChannel );
|
||||
if ( status ) {
|
||||
this->chidList.remove ( *chan );
|
||||
this->chidList.add ( *chan );
|
||||
}
|
||||
}
|
||||
else {
|
||||
status = false;
|
||||
}
|
||||
|
||||
this->unlock ();
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
//
|
||||
// considerable extra effort is taken in this routine to
|
||||
// guarantee that the lock is not held while blocking
|
||||
// in ::send () for buffer space.
|
||||
//
|
||||
void netiiu::sendPendingClaims ( tcpiiu &iiu, bool v42Ok, claimMsgCache &cache )
|
||||
{
|
||||
while ( 1 ) {
|
||||
while (1) {
|
||||
this->lock ();
|
||||
tsDLIterBD < nciu > chan ( this->chidList.last () );
|
||||
if ( ! chan.valid () ) {
|
||||
this->unlock ();
|
||||
return;
|
||||
}
|
||||
|
||||
bool status = cache.set ( *chan );
|
||||
if ( status ) {
|
||||
this->unlock ();
|
||||
break;
|
||||
}
|
||||
|
||||
this->unlock ();
|
||||
threadSleep ( 1.0 );
|
||||
}
|
||||
|
||||
int status = cache.deliverMsg ( iiu );
|
||||
if ( status != ECA_NORMAL ) {
|
||||
break;
|
||||
}
|
||||
|
||||
this->lock ();
|
||||
// if the channel was not deleted while the lock was off
|
||||
tsDLIterBD < nciu > chan ( this->chidList.last () );
|
||||
if ( chan.valid () ) {
|
||||
if ( cache.channelMatches ( *chan ) ) {
|
||||
if ( ! v42Ok ) {
|
||||
chan->connect ( iiu );
|
||||
}
|
||||
chan->attachChanToIIU ( iiu );
|
||||
}
|
||||
}
|
||||
this->unlock ();
|
||||
}
|
||||
}
|
||||
|
||||
bool netiiu::ca_v42_ok () const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool netiiu::ca_v41_ok () const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool netiiu::pushDatagramMsg ( const caHdr &, const void *, ca_uint16_t )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool netiiu::connectionInProgress ( const char *pChannelName, const osiSockAddr &addr ) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void netiiu::lastChannelDetachNotify ()
|
||||
{
|
||||
}
|
||||
|
||||
int netiiu::writeRequest ( unsigned, unsigned, unsigned, const void * )
|
||||
{
|
||||
return ECA_DISCONNCHID;
|
||||
}
|
||||
|
||||
int netiiu::writeNotifyRequest ( unsigned ioId, unsigned serverId, unsigned type, unsigned nElem, const void *pValue )
|
||||
{
|
||||
return ECA_DISCONNCHID;
|
||||
}
|
||||
|
||||
int netiiu::readCopyRequest ( unsigned ioId, unsigned serverId, unsigned type, unsigned nElem )
|
||||
{
|
||||
return ECA_DISCONNCHID;
|
||||
}
|
||||
|
||||
int netiiu::readNotifyRequest ( unsigned ioId, unsigned serverId, unsigned type, unsigned nElem )
|
||||
{
|
||||
return ECA_DISCONNCHID;
|
||||
}
|
||||
|
||||
int netiiu::createChannelRequest ( unsigned clientId, const char *pName, unsigned nameLength )
|
||||
{
|
||||
return ECA_DISCONNCHID;
|
||||
}
|
||||
|
||||
int netiiu::clearChannelRequest ( unsigned clientId, unsigned serverId )
|
||||
{
|
||||
return ECA_DISCONNCHID;
|
||||
}
|
||||
|
||||
int netiiu::subscriptionRequest ( unsigned ioId, unsigned serverId, unsigned type, unsigned nElem, unsigned mask )
|
||||
{
|
||||
return ECA_DISCONNCHID;
|
||||
}
|
||||
|
||||
int netiiu::subscriptionCancelRequest ( unsigned ioId, unsigned serverId, unsigned type, unsigned nElem )
|
||||
{
|
||||
return ECA_DISCONNCHID;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
|
||||
#ifndef netiiuPtr_ILh
|
||||
#define netiiuPtr_ILh
|
||||
|
||||
inline netiiuPtr::netiiuPtr () : piiu ( 0 )
|
||||
{
|
||||
}
|
||||
|
||||
inline netiiuPtr::~netiiuPtr ()
|
||||
{
|
||||
}
|
||||
|
||||
inline netiiu *netiiuPtr::pIIU () const
|
||||
{
|
||||
return this->piiu;
|
||||
}
|
||||
|
||||
inline void netiiuPtr::setPointer ( netiiu *p )
|
||||
{
|
||||
this->piiu = p;
|
||||
}
|
||||
|
||||
|
||||
#endif // netiiuPtr_ILh
|
||||
@@ -0,0 +1,35 @@
|
||||
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
*
|
||||
* L O S A L A M O S
|
||||
* Los Alamos National Laboratory
|
||||
* Los Alamos, New Mexico 87545
|
||||
*
|
||||
* Copyright, 1986, The Regents of the University of California.
|
||||
*
|
||||
*
|
||||
* Author Jeffrey O. Hill
|
||||
* johill@lanl.gov
|
||||
* 505 665 1831
|
||||
*/
|
||||
|
||||
#ifndef netiiu_ILh
|
||||
#define netiiu_ILh
|
||||
|
||||
inline netiiu::netiiu ( cac &cacIn ) :
|
||||
cacRef ( cacIn )
|
||||
{
|
||||
}
|
||||
|
||||
inline netiiu::~netiiu ()
|
||||
{
|
||||
}
|
||||
|
||||
inline cac & netiiu::clientCtx () const
|
||||
{
|
||||
return this->cacRef;
|
||||
}
|
||||
|
||||
#endif // netiiu_ILh
|
||||
@@ -15,6 +15,8 @@
|
||||
* 505 665 1831
|
||||
*/
|
||||
|
||||
extern "C" void cacNoConnHandler ( struct connection_handler_args args );
|
||||
|
||||
struct oldChannel : public cacChannel {
|
||||
public:
|
||||
oldChannel (caCh *pConnCallBack, void *pPrivate);
|
||||
@@ -42,6 +44,7 @@ private:
|
||||
static tsFreeList < struct oldChannel, 1024 > freeList;
|
||||
|
||||
friend int epicsShareAPI ca_array_get (chtype type, unsigned long count, chid pChan, void *pValue);
|
||||
friend void cacNoConnHandler ( struct connection_handler_args args );
|
||||
};
|
||||
|
||||
class getCallback : public cacNotify {
|
||||
|
||||
+115
-95
@@ -20,53 +20,6 @@
|
||||
|
||||
tsFreeList < struct oldChannel, 1024 > oldChannel::freeList;
|
||||
|
||||
oldChannel::oldChannel (caCh *pConnCallBackIn, void *pPrivateIn) :
|
||||
pConnCallBack (pConnCallBackIn), pPrivate (pPrivateIn), pAccessRightsFunc (0)
|
||||
{
|
||||
}
|
||||
|
||||
oldChannel::~oldChannel ()
|
||||
{
|
||||
this->lock ();
|
||||
if ( ! this->pConnCallBack ) {
|
||||
this->decrementOutstandingIO ();
|
||||
}
|
||||
this->unlock ();
|
||||
}
|
||||
|
||||
void oldChannel::destroy ()
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
void oldChannel::ioAttachNotify ()
|
||||
{
|
||||
this->lock ();
|
||||
if ( ! this->pConnCallBack ) {
|
||||
this->incrementOutstandingIO ();
|
||||
}
|
||||
this->unlock ();
|
||||
}
|
||||
|
||||
void oldChannel::ioReleaseNotify ()
|
||||
{
|
||||
this->lock ();
|
||||
if ( ! this->pConnCallBack ) {
|
||||
this->decrementOutstandingIO ();
|
||||
}
|
||||
this->unlock ();
|
||||
}
|
||||
|
||||
void oldChannel::setPrivatePointer (void *pPrivateIn)
|
||||
{
|
||||
this->pPrivate = pPrivateIn;
|
||||
}
|
||||
|
||||
void * oldChannel::privatePointer () const
|
||||
{
|
||||
return this->pPrivate;
|
||||
}
|
||||
|
||||
/*
|
||||
* cacAlreadyConnHandler ()
|
||||
* This is installed into channels which dont have
|
||||
@@ -78,89 +31,156 @@ extern "C" void cacAlreadyConnHandler (struct connection_handler_args)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* cacNoConnHandler ()
|
||||
* This is installed into channels which dont have
|
||||
* a connection handler before ca_pend_io() times
|
||||
* out so that we will properly decrement the pending
|
||||
* recv count in the future.
|
||||
*/
|
||||
extern "C" void cacNoConnHandler ( struct connection_handler_args args )
|
||||
{
|
||||
args.chid->lockOutstandingIO ();
|
||||
if ( args.chid->pConnCallBack == cacNoConnHandler ) {
|
||||
args.chid->pConnCallBack = cacAlreadyConnHandler;
|
||||
if ( args.op == CA_OP_CONN_UP ) {
|
||||
args.chid->decrementOutstandingIO ();
|
||||
}
|
||||
}
|
||||
args.chid->unlockOutstandingIO ();
|
||||
}
|
||||
|
||||
extern "C" void cacNoopAccesRightsHandler ( struct access_rights_handler_args )
|
||||
{
|
||||
}
|
||||
|
||||
oldChannel::oldChannel (caCh *pConnCallBackIn, void *pPrivateIn) :
|
||||
pPrivate ( pPrivateIn ), pAccessRightsFunc ( cacNoopAccesRightsHandler )
|
||||
{
|
||||
if ( ! pConnCallBackIn ) {
|
||||
this->pConnCallBack = cacNoConnHandler;
|
||||
}
|
||||
else {
|
||||
this->pConnCallBack = pConnCallBackIn;
|
||||
}
|
||||
}
|
||||
|
||||
oldChannel::~oldChannel ()
|
||||
{
|
||||
if ( this->pConnCallBack == cacNoConnHandler ) {
|
||||
this->decrementOutstandingIO ();
|
||||
}
|
||||
}
|
||||
|
||||
void oldChannel::destroy ()
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
void oldChannel::ioAttachNotify ()
|
||||
{
|
||||
this->lockOutstandingIO ();
|
||||
if ( this->pConnCallBack == cacNoConnHandler ) {
|
||||
this->incrementOutstandingIO ();
|
||||
}
|
||||
this->unlockOutstandingIO ();
|
||||
}
|
||||
|
||||
void oldChannel::ioReleaseNotify ()
|
||||
{
|
||||
this->lockOutstandingIO ();
|
||||
if ( this->pConnCallBack == cacNoConnHandler ) {
|
||||
this->decrementOutstandingIO ();
|
||||
}
|
||||
this->unlockOutstandingIO ();
|
||||
}
|
||||
|
||||
void oldChannel::setPrivatePointer ( void *pPrivateIn )
|
||||
{
|
||||
this->pPrivate = pPrivateIn;
|
||||
}
|
||||
|
||||
void * oldChannel::privatePointer () const
|
||||
{
|
||||
return this->pPrivate;
|
||||
}
|
||||
|
||||
void oldChannel::connectTimeoutNotify ()
|
||||
{
|
||||
this->lock ();
|
||||
if ( ! this->pConnCallBack ) {
|
||||
this->lockOutstandingIO ();
|
||||
if ( this->pConnCallBack == cacNoConnHandler ) {
|
||||
this->pConnCallBack = cacAlreadyConnHandler;
|
||||
}
|
||||
this->unlock ();
|
||||
this->unlockOutstandingIO ();
|
||||
}
|
||||
|
||||
void oldChannel::connectNotify ()
|
||||
{
|
||||
this->lock ();
|
||||
if ( this->pConnCallBack ) {
|
||||
caCh *pCCB = this->pConnCallBack;
|
||||
struct connection_handler_args args;
|
||||
args.chid = this;
|
||||
args.op = CA_OP_CONN_UP;
|
||||
(*pCCB) (args);
|
||||
}
|
||||
else {
|
||||
this->pConnCallBack = cacAlreadyConnHandler;
|
||||
this->decrementOutstandingIO ();
|
||||
}
|
||||
this->unlock ();
|
||||
this->lockOutstandingIO ();
|
||||
struct connection_handler_args args;
|
||||
args.chid = this;
|
||||
args.op = CA_OP_CONN_UP;
|
||||
(*this->pConnCallBack) (args);
|
||||
this->unlockOutstandingIO ();
|
||||
}
|
||||
|
||||
void oldChannel::disconnectNotify ()
|
||||
{
|
||||
this->lock ();
|
||||
if ( this->pConnCallBack ) {
|
||||
struct connection_handler_args args;
|
||||
args.chid = this;
|
||||
args.op = CA_OP_CONN_DOWN;
|
||||
(*this->pConnCallBack) (args);
|
||||
}
|
||||
this->unlock ();
|
||||
this->lockOutstandingIO ();
|
||||
struct connection_handler_args args;
|
||||
args.chid = this;
|
||||
args.op = CA_OP_CONN_DOWN;
|
||||
(*this->pConnCallBack) ( args );
|
||||
this->unlockOutstandingIO ();
|
||||
}
|
||||
|
||||
void oldChannel::accessRightsNotify (caar ar)
|
||||
int oldChannel::changeConnCallBack ( caCh *pfunc )
|
||||
{
|
||||
this->lock ();
|
||||
if ( this->pAccessRightsFunc ) {
|
||||
struct access_rights_handler_args args;
|
||||
args.chid = this;
|
||||
args.ar = ar;
|
||||
( *this->pAccessRightsFunc ) ( args );
|
||||
}
|
||||
this->unlock ();
|
||||
}
|
||||
|
||||
int oldChannel::changeConnCallBack (caCh *pfunc)
|
||||
{
|
||||
this->lock ();
|
||||
if ( pfunc == 0) {
|
||||
if ( this->pConnCallBack != 0 ) {
|
||||
if ( this->pConnCallBack != cacAlreadyConnHandler ) {
|
||||
this->lockOutstandingIO ();
|
||||
if ( ! pfunc ) {
|
||||
if ( this->pConnCallBack != cacNoConnHandler &&
|
||||
this->pConnCallBack != cacAlreadyConnHandler ) {
|
||||
if ( this->state () == cs_never_conn ) {
|
||||
this->incrementOutstandingIO ();
|
||||
this->pConnCallBack = 0;
|
||||
this->pConnCallBack = cacNoConnHandler;
|
||||
}
|
||||
else {
|
||||
this->pConnCallBack = cacAlreadyConnHandler;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ( this->pConnCallBack == 0 ) {
|
||||
if ( this->pConnCallBack == cacNoConnHandler ) {
|
||||
this->decrementOutstandingIO ();
|
||||
}
|
||||
this->pConnCallBack = pfunc;
|
||||
}
|
||||
this->unlock ();
|
||||
this->unlockOutstandingIO ();
|
||||
|
||||
return ECA_NORMAL;
|
||||
}
|
||||
|
||||
int oldChannel::replaceAccessRightsEvent (caArh *pfunc)
|
||||
void oldChannel::accessRightsNotify ( caar ar )
|
||||
{
|
||||
this->lock ();
|
||||
struct access_rights_handler_args args;
|
||||
args.chid = this;
|
||||
args.ar = ar;
|
||||
( *this->pAccessRightsFunc ) ( args );
|
||||
}
|
||||
|
||||
int oldChannel::replaceAccessRightsEvent ( caArh *pfunc )
|
||||
{
|
||||
if ( ! pfunc ) {
|
||||
pfunc = cacNoopAccesRightsHandler;
|
||||
}
|
||||
|
||||
this->pAccessRightsFunc = pfunc;
|
||||
if ( pfunc && this->connected () ) {
|
||||
if ( this->connected () ) {
|
||||
struct access_rights_handler_args args;
|
||||
args.chid = this;
|
||||
args.ar = this->accessRights ();
|
||||
(*pfunc) (args);
|
||||
}
|
||||
this->unlock ();
|
||||
|
||||
return ECA_NORMAL;
|
||||
}
|
||||
|
||||
@@ -18,8 +18,8 @@
|
||||
|
||||
#include <iocinf.h>
|
||||
|
||||
processThread::processThread (cac *pcacIn) :
|
||||
osiThread ( "CAC-process", threadGetStackSize (threadStackSmall), threadPriorityMedium ),
|
||||
recvProcessThread::recvProcessThread (cac *pcacIn) :
|
||||
osiThread ( "CAC-recv-process", threadGetStackSize (threadStackSmall), threadPriorityMedium ),
|
||||
pcac ( pcacIn ),
|
||||
enableRefCount ( 0u ),
|
||||
blockingForCompletion ( 0u ),
|
||||
@@ -29,18 +29,18 @@ processThread::processThread (cac *pcacIn) :
|
||||
this->start ();
|
||||
}
|
||||
|
||||
processThread::~processThread ()
|
||||
recvProcessThread::~recvProcessThread ()
|
||||
{
|
||||
this->signalShutDown ();
|
||||
while ( ! this->exit.wait ( 10.0 ) ) {
|
||||
printf ("processThread::~processThread (): Warning, thread object destroyed before thread exit \n");
|
||||
errlogPrintf ("recvProcessThread::~recvProcessThread (): Warning, thread object destroyed before thread exit \n");
|
||||
}
|
||||
}
|
||||
|
||||
void processThread::entryPoint ()
|
||||
void recvProcessThread::entryPoint ()
|
||||
{
|
||||
int status = ca_attach_context ( this->pcac );
|
||||
SEVCHK ( status, "attaching to client context in process thread" );
|
||||
SEVCHK ( status, "attaching to client context in recv process thread" );
|
||||
while ( ! this->shutDown ) {
|
||||
|
||||
this->mutex.lock ();
|
||||
@@ -58,18 +58,18 @@ void processThread::entryPoint ()
|
||||
this->processingDone.signal ();
|
||||
}
|
||||
|
||||
this->pcac->recvActivity.wait ();
|
||||
this->recvActivity.wait ();
|
||||
}
|
||||
this->exit.signal ();
|
||||
}
|
||||
|
||||
void processThread::signalShutDown ()
|
||||
void recvProcessThread::signalShutDown ()
|
||||
{
|
||||
this->shutDown = true;
|
||||
this->pcac->recvActivity.signal ();
|
||||
this->recvActivity.signal ();
|
||||
}
|
||||
|
||||
void processThread::enable ()
|
||||
void recvProcessThread::enable ()
|
||||
{
|
||||
unsigned copy;
|
||||
|
||||
@@ -80,11 +80,11 @@ void processThread::enable ()
|
||||
this->mutex.unlock ();
|
||||
|
||||
if ( copy == 0u ) {
|
||||
this->pcac->recvActivity.signal ();
|
||||
this->recvActivity.signal ();
|
||||
}
|
||||
}
|
||||
|
||||
void processThread::disable ()
|
||||
void recvProcessThread::disable ()
|
||||
{
|
||||
bool waitNeeded;
|
||||
|
||||
@@ -111,4 +111,9 @@ void processThread::disable ()
|
||||
this->processingDone.signal ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void recvProcessThread::signalActivity ()
|
||||
{
|
||||
this->recvActivity.signal ();
|
||||
}
|
||||
+252
-170
@@ -57,23 +57,44 @@
|
||||
#include "iocinf.h"
|
||||
#include "taskwd.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
# define debugPrintf(argsInParen) printf argsInParen
|
||||
#else
|
||||
# define debugPrintf(argsInParen)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* one socket per client so we will get the ECONNREFUSED
|
||||
* error code (and then delete the client)
|
||||
*/
|
||||
struct one_client {
|
||||
ELLNODE node;
|
||||
struct sockaddr_in from;
|
||||
SOCKET sock;
|
||||
class repeaterClient : public tsDLNode < repeaterClient > {
|
||||
public:
|
||||
repeaterClient ( const osiSockAddr &from );
|
||||
bool connect ();
|
||||
bool sendConfirm ();
|
||||
bool sendMessage ( const void *pBuf, unsigned bufSize );
|
||||
void destroy ();
|
||||
bool verify ();
|
||||
bool identicalAddress ( const osiSockAddr &from );
|
||||
bool identicalPort ( const osiSockAddr &from );
|
||||
void * operator new ( size_t size );
|
||||
void operator delete ( void *pCadaver, size_t size );
|
||||
private:
|
||||
osiSockAddr from;
|
||||
SOCKET sock;
|
||||
static tsFreeList < class repeaterClient, 0x20 > freeList;
|
||||
~repeaterClient ();
|
||||
unsigned port () const;
|
||||
};
|
||||
|
||||
/*
|
||||
* these can be external since there is only one instance
|
||||
* per machine so we dont care about reentrancy
|
||||
*/
|
||||
static ELLLIST client_list;
|
||||
static tsDLList < repeaterClient > client_list;
|
||||
tsFreeList < repeaterClient, 0x20 > repeaterClient::freeList;
|
||||
|
||||
static char buf[ETHERNET_MAX_UDP];
|
||||
static char buf [MAX_UDP_RECV];
|
||||
|
||||
static const unsigned short PORT_ANY = 0u;
|
||||
|
||||
@@ -86,14 +107,14 @@ typedef struct {
|
||||
/*
|
||||
* makeSocket()
|
||||
*/
|
||||
LOCAL makeSocketReturn makeSocket (unsigned short port, int reuseAddr)
|
||||
LOCAL makeSocketReturn makeSocket ( unsigned short port, bool reuseAddr )
|
||||
{
|
||||
int status;
|
||||
struct sockaddr_in bd;
|
||||
makeSocketReturn msr;
|
||||
int flag;
|
||||
|
||||
msr.sock = socket (AF_INET, SOCK_DGRAM, 0);
|
||||
msr.sock = socket ( AF_INET, SOCK_DGRAM, 0 );
|
||||
if ( msr.sock == INVALID_SOCKET ) {
|
||||
msr.errNumber = SOCKERRNO;
|
||||
msr.pErrStr = SOCKERRSTR (msr.errNumber);
|
||||
@@ -110,18 +131,18 @@ LOCAL makeSocketReturn makeSocket (unsigned short port, int reuseAddr)
|
||||
bd.sin_addr.s_addr = htonl (INADDR_ANY);
|
||||
bd.sin_port = htons (port);
|
||||
status = bind (msr.sock, (struct sockaddr *)&bd, (int)sizeof(bd));
|
||||
if (status<0) {
|
||||
if ( status < 0 ) {
|
||||
msr.errNumber = SOCKERRNO;
|
||||
msr.pErrStr = SOCKERRSTR (msr.errNumber);
|
||||
msr.pErrStr = SOCKERRSTR ( msr.errNumber );
|
||||
socket_close (msr.sock);
|
||||
msr.sock = INVALID_SOCKET;
|
||||
return msr;
|
||||
}
|
||||
if (reuseAddr) {
|
||||
flag = TRUE;
|
||||
flag = true;
|
||||
status = setsockopt ( msr.sock, SOL_SOCKET, SO_REUSEADDR,
|
||||
(char *)&flag, sizeof (flag) );
|
||||
if (status<0) {
|
||||
(char *) &flag, sizeof (flag) );
|
||||
if ( status < 0 ) {
|
||||
int errnoCpy = SOCKERRNO;
|
||||
ca_printf (
|
||||
"%s: set socket option failed because \"%s\"\n",
|
||||
@@ -135,131 +156,233 @@ LOCAL makeSocketReturn makeSocket (unsigned short port, int reuseAddr)
|
||||
return msr;
|
||||
}
|
||||
|
||||
repeaterClient::repeaterClient ( const osiSockAddr &fromIn ) :
|
||||
from ( fromIn ), sock ( INVALID_SOCKET )
|
||||
{
|
||||
debugPrintf ( ( "new client %u\n", ntohs ( from.ia.sin_port ) ) );
|
||||
}
|
||||
|
||||
bool repeaterClient::connect ()
|
||||
{
|
||||
int status;
|
||||
makeSocketReturn msr;
|
||||
|
||||
msr = makeSocket ( PORT_ANY, false );
|
||||
if ( msr.sock == INVALID_SOCKET ) {
|
||||
ca_printf ( "%s: no client sock because %d=\"%s\"\n",
|
||||
__FILE__, msr.errNumber, msr.pErrStr );
|
||||
return false;
|
||||
}
|
||||
|
||||
this->sock = msr.sock;
|
||||
|
||||
status = ::connect ( this->sock, &this->from.sa, sizeof ( this->from.sa ) );
|
||||
if ( status < 0 ) {
|
||||
int errnoCpy = SOCKERRNO;
|
||||
|
||||
ca_printf (
|
||||
"%s: unable to connect client sock because \"%s\"\n",
|
||||
__FILE__, SOCKERRSTR ( errnoCpy ) );
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool repeaterClient::sendConfirm ()
|
||||
{
|
||||
int status;
|
||||
|
||||
caHdr confirm;
|
||||
memset ( (char *) &confirm, '\0', sizeof (confirm) );
|
||||
confirm.m_cmmd = htons ( REPEATER_CONFIRM );
|
||||
confirm.m_available = this->from.ia.sin_addr.s_addr;
|
||||
status = send ( this->sock, (char *) &confirm,
|
||||
sizeof (confirm), 0 );
|
||||
if ( status >= 0 ) {
|
||||
assert ( status == sizeof ( confirm ) );
|
||||
return true;
|
||||
}
|
||||
else if ( SOCKERRNO == SOCK_ECONNREFUSED ) {
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
ca_printf ( "CA Repeater: confirm err was \"%s\"\n",
|
||||
SOCKERRSTR (SOCKERRNO) );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool repeaterClient::sendMessage ( const void *pBuf, unsigned bufSize )
|
||||
{
|
||||
int status;
|
||||
|
||||
status = send ( this->sock, (char *) pBuf, bufSize, 0 );
|
||||
if ( status >= 0 ) {
|
||||
assert ( status == bufSize );
|
||||
debugPrintf ( ("Sent to %u\n", ntohs ( this->from.ia.sin_port ) ) );
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
int errnoCpy = SOCKERRNO;
|
||||
if ( errnoCpy == SOCK_ECONNREFUSED ) {
|
||||
debugPrintf ( ("Client refused message %u\n", ntohs ( this->from.ia.sin_port ) ) );
|
||||
}
|
||||
else {
|
||||
debugPrintf ( ( "CA Repeater: UDP send err was \"%s\"\n", SOCKERRSTR (errnoCpy) ) );
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
repeaterClient::~repeaterClient ()
|
||||
{
|
||||
if ( this->sock != INVALID_SOCKET ) {
|
||||
socket_close ( this->sock );
|
||||
}
|
||||
debugPrintf ( ( "Deleted client %u\n", ntohs ( this->from.ia.sin_port ) ) );
|
||||
}
|
||||
|
||||
inline void * repeaterClient::operator new ( size_t size )
|
||||
{
|
||||
return repeaterClient::freeList.allocate ( size );
|
||||
}
|
||||
|
||||
inline void repeaterClient::operator delete ( void *pCadaver, size_t size )
|
||||
{
|
||||
repeaterClient::freeList.release ( pCadaver, size );
|
||||
}
|
||||
|
||||
inline void repeaterClient::destroy ()
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
inline unsigned repeaterClient::port () const
|
||||
{
|
||||
return ntohs ( this->from.ia.sin_port );
|
||||
}
|
||||
|
||||
inline bool repeaterClient::identicalAddress ( const osiSockAddr &from )
|
||||
{
|
||||
if ( from.sa.sa_family == this->from.sa.sa_family ) {
|
||||
if ( from.ia.sin_port == this->from.ia.sin_port) {
|
||||
if ( from.ia.sin_addr.s_addr == this->from.ia.sin_addr.s_addr ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool repeaterClient::identicalPort ( const osiSockAddr &from )
|
||||
{
|
||||
if ( from.sa.sa_family == this->from.sa.sa_family ) {
|
||||
if ( from.ia.sin_port == this->from.ia.sin_port) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool repeaterClient::verify ()
|
||||
{
|
||||
makeSocketReturn msr;
|
||||
msr = makeSocket ( this->port (), false );
|
||||
if ( msr.sock != INVALID_SOCKET ) {
|
||||
socket_close ( msr.sock );
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
/*
|
||||
* win sock does not set SOCKERRNO when this fails
|
||||
*/
|
||||
if ( msr.errNumber != SOCK_EADDRINUSE ) {
|
||||
ca_printf (
|
||||
"CA Repeater: bind test err was %d=\"%s\"\n",
|
||||
msr.errNumber, msr.pErrStr );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* verifyClients()
|
||||
* (this is required because solaris has a half baked version of sockets)
|
||||
*/
|
||||
LOCAL void verifyClients()
|
||||
{
|
||||
ELLLIST theClients;
|
||||
struct one_client *pclient;
|
||||
makeSocketReturn msr;
|
||||
static tsDLList < repeaterClient > theClients;
|
||||
repeaterClient *pclient;
|
||||
|
||||
ellInit(&theClients);
|
||||
while ( (pclient=(struct one_client *)ellGet(&client_list)) ) {
|
||||
ellAdd (&theClients, &pclient->node);
|
||||
|
||||
msr = makeSocket ( ntohs (pclient->from.sin_port), FALSE );
|
||||
if ( msr.sock != INVALID_SOCKET ) {
|
||||
#ifdef DEBUG
|
||||
ca_printf ("Deleted client %d\n",
|
||||
ntohs (pclient->from.sin_port) );
|
||||
#endif
|
||||
ellDelete (&theClients, &pclient->node);
|
||||
socket_close (msr.sock);
|
||||
socket_close (pclient->sock);
|
||||
free (pclient);
|
||||
while ( pclient = client_list.get () ) {
|
||||
if ( pclient->verify () ) {
|
||||
theClients.add ( *pclient );
|
||||
}
|
||||
else {
|
||||
/*
|
||||
* win sock does not set SOCKERRNO when this fails
|
||||
*/
|
||||
if ( msr.errNumber != SOCK_EADDRINUSE ) {
|
||||
ca_printf (
|
||||
"CA Repeater: bind test err was %d=\"%s\"\n",
|
||||
msr.errNumber, msr.pErrStr);
|
||||
}
|
||||
pclient->destroy ();
|
||||
}
|
||||
}
|
||||
ellConcat (&client_list, &theClients);
|
||||
client_list.add ( theClients );
|
||||
}
|
||||
|
||||
/*
|
||||
* fanOut()
|
||||
*/
|
||||
LOCAL void fanOut (struct sockaddr_in *pFrom, const char *pMsg, unsigned msgSize)
|
||||
LOCAL void fanOut ( const osiSockAddr &from, const void *pMsg, unsigned msgSize )
|
||||
{
|
||||
ELLLIST theClients;
|
||||
struct one_client *pclient;
|
||||
int status;
|
||||
int verify = FALSE;
|
||||
static tsDLList < repeaterClient > theClients;
|
||||
repeaterClient *pclient;
|
||||
|
||||
ellInit(&theClients);
|
||||
while ( ( pclient = (struct one_client *) ellGet (&client_list) ) ) {
|
||||
ellAdd(&theClients, &pclient->node);
|
||||
|
||||
/*
|
||||
* Dont reflect back to sender
|
||||
*/
|
||||
if(pFrom->sin_port == pclient->from.sin_port &&
|
||||
pFrom->sin_addr.s_addr == pclient->from.sin_addr.s_addr){
|
||||
while ( pclient = client_list.get () ) {
|
||||
theClients.add ( *pclient );
|
||||
/* Dont reflect back to sender */
|
||||
if ( pclient->identicalAddress ( from ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
status = send ( pclient->sock, (char *)pMsg, msgSize, 0 );
|
||||
if ( status >= 0 ) {
|
||||
#ifdef DEBUG
|
||||
ca_printf ("Sent to %d\n",
|
||||
ntohs (pclient->from.sin_port));
|
||||
#endif
|
||||
}
|
||||
if ( status < 0 ) {
|
||||
int errnoCpy = SOCKERRNO;
|
||||
if ( errnoCpy == SOCK_ECONNREFUSED ) {
|
||||
#ifdef DEBUG
|
||||
ca_printf ("Deleted client %d\n",
|
||||
ntohs (pclient->from.sin_port));
|
||||
#endif
|
||||
verify = TRUE;
|
||||
}
|
||||
else {
|
||||
ca_printf (
|
||||
"CA Repeater: UDP fan out err was \"%s\"\n",
|
||||
SOCKERRSTR(errnoCpy));
|
||||
if ( ! pclient->sendMessage ( pMsg, msgSize ) ) {
|
||||
if ( ! pclient->verify () ) {
|
||||
theClients.remove ( *pclient );
|
||||
pclient->destroy ();
|
||||
}
|
||||
}
|
||||
}
|
||||
ellConcat(&client_list, &theClients);
|
||||
|
||||
if (verify) {
|
||||
verifyClients ();
|
||||
}
|
||||
client_list.add ( theClients );
|
||||
}
|
||||
|
||||
/*
|
||||
* register_new_client()
|
||||
*/
|
||||
LOCAL void register_new_client (struct sockaddr_in *pFrom)
|
||||
LOCAL void register_new_client ( osiSockAddr &from )
|
||||
{
|
||||
int status;
|
||||
struct one_client *pclient;
|
||||
caHdr confirm;
|
||||
caHdr noop;
|
||||
int newClient = FALSE;
|
||||
bool newClient = false;
|
||||
makeSocketReturn msr;
|
||||
|
||||
if (pFrom->sin_family != AF_INET) {
|
||||
if ( from.sa.sa_family != AF_INET ) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* the repeater and its clients must be on the same host
|
||||
*/
|
||||
if ( htonl(INADDR_LOOPBACK) != pFrom->sin_addr.s_addr ) {
|
||||
if ( htonl ( INADDR_LOOPBACK ) != from.ia.sin_addr.s_addr ) {
|
||||
static SOCKET testSock = INVALID_SOCKET;
|
||||
static int init;
|
||||
struct sockaddr_in ina;
|
||||
static bool init = false;
|
||||
|
||||
if ( ! init ) {
|
||||
msr = makeSocket (PORT_ANY, TRUE);
|
||||
msr = makeSocket ( PORT_ANY, true );
|
||||
if ( msr.sock == INVALID_SOCKET ) {
|
||||
ca_printf("%s: Unable to create repeater bind test socket because %d=\"%s\"\n",
|
||||
__FILE__, msr.errNumber, msr.pErrStr);
|
||||
ca_printf ( "%s: Unable to create repeater bind test socket because %d=\"%s\"\n",
|
||||
__FILE__, msr.errNumber, msr.pErrStr );
|
||||
}
|
||||
else {
|
||||
testSock = msr.sock;
|
||||
}
|
||||
init = TRUE;
|
||||
init = true;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -272,12 +395,14 @@ LOCAL void register_new_client (struct sockaddr_in *pFrom)
|
||||
* to current code.
|
||||
*/
|
||||
if ( testSock != INVALID_SOCKET ) {
|
||||
ina = *pFrom;
|
||||
ina.sin_port = PORT_ANY;
|
||||
osiSockAddr addr;
|
||||
|
||||
addr = from;
|
||||
addr.ia.sin_port = PORT_ANY;
|
||||
|
||||
/* we can only bind to a local address */
|
||||
status = bind ( testSock, (struct sockaddr *) &ina, (int) sizeof (ina) );
|
||||
if (status) {
|
||||
status = bind ( testSock, &addr.sa, sizeof ( addr ) );
|
||||
if ( status ) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -286,84 +411,45 @@ LOCAL void register_new_client (struct sockaddr_in *pFrom)
|
||||
}
|
||||
}
|
||||
|
||||
for ( pclient = (struct one_client *) ellFirst (&client_list);
|
||||
pclient; pclient = (struct one_client *) ellNext (&pclient->node) ){
|
||||
|
||||
if ( pFrom->sin_port == pclient->from.sin_port ) {
|
||||
tsDLIterBD < repeaterClient > pclient = client_list.first ();
|
||||
while ( pclient.valid () ) {
|
||||
if ( pclient->identicalPort ( from ) ) {
|
||||
break;
|
||||
}
|
||||
pclient = pclient.itemAfter ();
|
||||
}
|
||||
|
||||
if ( ! pclient ) {
|
||||
pclient = (struct one_client *) calloc ( 1, sizeof (*pclient) );
|
||||
if ( ! pclient ) {
|
||||
if ( ! pclient.valid () ) {
|
||||
pclient = new repeaterClient ( from );
|
||||
if ( ! pclient.valid () ) {
|
||||
ca_printf ( "%s: no memory for new client\n", __FILE__ );
|
||||
return;
|
||||
}
|
||||
|
||||
msr = makeSocket (PORT_ANY, FALSE);
|
||||
if ( msr.sock==INVALID_SOCKET ) {
|
||||
free ( pclient );
|
||||
ca_printf ( "%s: no client sock because %d=\"%s\"\n",
|
||||
__FILE__, msr.errNumber, msr.pErrStr );
|
||||
if ( ! pclient->connect () ) {
|
||||
pclient->destroy ();
|
||||
return;
|
||||
}
|
||||
|
||||
pclient->sock = msr.sock;
|
||||
|
||||
status = connect ( pclient->sock,
|
||||
(struct sockaddr *) pFrom,
|
||||
sizeof ( *pFrom ) );
|
||||
if ( status < 0 ) {
|
||||
int errnoCpy = SOCKERRNO;
|
||||
|
||||
ca_printf (
|
||||
"%s: unable to connect client sock because \"%s\"\n",
|
||||
__FILE__, SOCKERRSTR (errnoCpy) );
|
||||
|
||||
socket_close ( pclient->sock );
|
||||
free ( pclient );
|
||||
return;
|
||||
}
|
||||
|
||||
pclient->from = *pFrom;
|
||||
|
||||
ellAdd ( &client_list, &pclient->node );
|
||||
newClient = TRUE;
|
||||
#ifdef DEBUG
|
||||
ca_printf ( "Added %d\n", ntohs (pFrom->sin_port) );
|
||||
#endif
|
||||
client_list.add ( *pclient );
|
||||
newClient = true;
|
||||
}
|
||||
|
||||
memset ( (char *) &confirm, '\0', sizeof (confirm) );
|
||||
confirm.m_cmmd = htons (REPEATER_CONFIRM);
|
||||
confirm.m_available = pFrom->sin_addr.s_addr;
|
||||
status = send ( pclient->sock, (char *) &confirm,
|
||||
sizeof (confirm), 0 );
|
||||
if ( status >= 0 ) {
|
||||
assert ( status == sizeof (confirm) );
|
||||
}
|
||||
else if ( SOCKERRNO == SOCK_ECONNREFUSED ){
|
||||
#ifdef DEBUG
|
||||
ca_printf ( "Deleted repeater client=%d sending ack\n",
|
||||
ntohs (pFrom->sin_port) );
|
||||
#endif
|
||||
ellDelete ( &client_list, &pclient->node );
|
||||
socket_close ( pclient->sock );
|
||||
free ( pclient );
|
||||
}
|
||||
else {
|
||||
ca_printf ( "CA Repeater: confirm err was \"%s\"\n",
|
||||
SOCKERRSTR (SOCKERRNO) );
|
||||
if ( ! pclient->sendConfirm () ) {
|
||||
client_list.remove (*pclient );
|
||||
pclient->destroy ();
|
||||
debugPrintf ( ( "Deleted repeater client=%u (error while sending ack)\n",
|
||||
ntohs (from.ia.sin_port) ) );
|
||||
}
|
||||
|
||||
/*
|
||||
* send a noop message to all other clients so that we dont
|
||||
* accumulate sockets when there are no beacons
|
||||
*/
|
||||
memset ( (char *) &noop, '\0', sizeof (noop) );
|
||||
confirm.m_cmmd = htons (CA_PROTO_NOOP);
|
||||
fanOut ( pFrom, (char *)&noop, sizeof (noop) );
|
||||
caHdr noop;
|
||||
memset ( (char *) &noop, '\0', sizeof ( noop ) );
|
||||
noop.m_cmmd = htons ( CA_PROTO_NOOP );
|
||||
fanOut ( from, &noop, sizeof ( noop ) );
|
||||
|
||||
if ( newClient ) {
|
||||
/*
|
||||
@@ -389,8 +475,8 @@ void epicsShareAPI ca_repeater ()
|
||||
{
|
||||
int size;
|
||||
SOCKET sock;
|
||||
struct sockaddr_in from;
|
||||
int from_size = sizeof from;
|
||||
osiSockAddr from;
|
||||
int from_size = sizeof ( from );
|
||||
unsigned short port;
|
||||
makeSocketReturn msr;
|
||||
|
||||
@@ -398,9 +484,7 @@ void epicsShareAPI ca_repeater ()
|
||||
|
||||
port = envGetInetPortConfigParam ( &EPICS_CA_REPEATER_PORT, CA_REPEATER_PORT );
|
||||
|
||||
ellInit(&client_list);
|
||||
|
||||
msr = makeSocket (port, TRUE);
|
||||
msr = makeSocket ( port, true );
|
||||
if ( msr.sock == INVALID_SOCKET ) {
|
||||
/*
|
||||
* test for server was already started
|
||||
@@ -417,15 +501,13 @@ void epicsShareAPI ca_repeater ()
|
||||
|
||||
sock = msr.sock;
|
||||
|
||||
#ifdef DEBUG
|
||||
ca_printf ("CA Repeater: Attached and initialized\n");
|
||||
#endif
|
||||
debugPrintf ( ( "CA Repeater: Attached and initialized\n" ) );
|
||||
|
||||
while (TRUE) {
|
||||
while ( true ) {
|
||||
caHdr *pMsg;
|
||||
|
||||
size = recvfrom ( sock, buf, sizeof (buf), 0,
|
||||
(struct sockaddr *)&from, &from_size );
|
||||
&from.sa, &from_size );
|
||||
if ( size < 0 ) {
|
||||
int errnoCpy = SOCKERRNO;
|
||||
# ifdef linux
|
||||
@@ -449,8 +531,8 @@ void epicsShareAPI ca_repeater ()
|
||||
* will register a new client
|
||||
*/
|
||||
if ( ( (size_t) size) >= sizeof (*pMsg) ) {
|
||||
if ( ntohs(pMsg->m_cmmd) == REPEATER_REGISTER ) {
|
||||
register_new_client (&from);
|
||||
if ( ntohs ( pMsg->m_cmmd ) == REPEATER_REGISTER ) {
|
||||
register_new_client ( from );
|
||||
|
||||
/*
|
||||
* strip register client message
|
||||
@@ -463,21 +545,21 @@ void epicsShareAPI ca_repeater ()
|
||||
}
|
||||
}
|
||||
else if (size == 0) {
|
||||
register_new_client (&from);
|
||||
register_new_client ( from );
|
||||
continue;
|
||||
}
|
||||
|
||||
fanOut (&from, (char *) pMsg, size);
|
||||
fanOut ( from, pMsg, size );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* caRepeaterThread ()
|
||||
*/
|
||||
void caRepeaterThread (void * /* pDummy */ )
|
||||
void caRepeaterThread ( void * /* pDummy */ )
|
||||
{
|
||||
taskwdInsert (threadGetIdSelf(), NULL, NULL);
|
||||
ca_repeater();
|
||||
taskwdInsert ( threadGetIdSelf(), NULL, NULL );
|
||||
ca_repeater ();
|
||||
}
|
||||
|
||||
|
||||
|
||||
+133
-209
@@ -13,50 +13,40 @@
|
||||
* Author Jeffrey O. Hill
|
||||
* johill@lanl.gov
|
||||
* 505 665 1831
|
||||
*
|
||||
* Notes:
|
||||
* 1) when rdix is equal to wtix it indicates that the entire buffer is
|
||||
* available to be read, and therefore nothing can be written.
|
||||
* 2) the byte at index rdix + 1 is the next byte to read.
|
||||
* 3) the byte at index wtix is the next byte to write.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "ringBuffer.h"
|
||||
|
||||
static const unsigned ringIndexMask = nElementsInRing-1;
|
||||
static const unsigned ringIndexMask = nElementsInRing - 1;
|
||||
|
||||
/*
|
||||
* cacRingBufferConstruct ()
|
||||
*/
|
||||
int cacRingBufferConstruct (ringBuffer *pBuf)
|
||||
bool cacRingBufferConstruct ( ringBuffer *pBuf )
|
||||
{
|
||||
pBuf->shutDown = 0u;
|
||||
pBuf->rdix = 0u;
|
||||
pBuf->wtix = 1u;
|
||||
|
||||
pBuf->readSignal = semBinaryCreate (semEmpty);
|
||||
if (!pBuf->readSignal) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
pBuf->writeSignal = semBinaryCreate (semEmpty);
|
||||
if (!pBuf->writeSignal) {
|
||||
semBinaryDestroy (pBuf->readSignal);
|
||||
return -1;
|
||||
}
|
||||
|
||||
pBuf->readLock = semMutexCreate ();
|
||||
if (!pBuf->readLock) {
|
||||
semBinaryDestroy (pBuf->readSignal);
|
||||
semBinaryDestroy (pBuf->writeSignal);
|
||||
return -1;
|
||||
if ( ! pBuf->readLock ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
pBuf->writeLock = semMutexCreate ();
|
||||
if (!pBuf->writeLock) {
|
||||
semBinaryDestroy (pBuf->readSignal);
|
||||
semBinaryDestroy (pBuf->writeSignal);
|
||||
semMutexDestroy (pBuf->readLock);
|
||||
return -1;
|
||||
if ( ! pBuf->writeLock ) {
|
||||
semMutexDestroy ( pBuf->readLock );
|
||||
return false;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -64,35 +54,23 @@ int cacRingBufferConstruct (ringBuffer *pBuf)
|
||||
*/
|
||||
void cacRingBufferDestroy (ringBuffer *pBuf)
|
||||
{
|
||||
semBinaryDestroy (pBuf->readSignal);
|
||||
semBinaryDestroy (pBuf->writeSignal);
|
||||
semMutexDestroy (pBuf->readLock);
|
||||
semMutexDestroy (pBuf->writeLock);
|
||||
}
|
||||
|
||||
/*
|
||||
* cacRingBufferShutDown ();
|
||||
*/
|
||||
void cacRingBufferShutDown (ringBuffer *pBuf)
|
||||
{
|
||||
pBuf->shutDown = 1u;
|
||||
semBinaryGive (pBuf->readSignal);
|
||||
semBinaryGive (pBuf->writeSignal);
|
||||
semMutexDestroy ( pBuf->readLock );
|
||||
semMutexDestroy ( pBuf->writeLock );
|
||||
}
|
||||
|
||||
/*
|
||||
* cacRingBufferReadSize ()
|
||||
*/
|
||||
static inline unsigned cacRingBufferReadSize (ringBuffer *pBuf)
|
||||
static inline unsigned cacRingBufferReadSize ( ringBuffer *pBuf )
|
||||
{
|
||||
unsigned long count;
|
||||
|
||||
if ( pBuf->wtix <= pBuf->rdix ) {
|
||||
static const unsigned bufSizeM1 = sizeof (pBuf->buf) - 1u;
|
||||
static const unsigned bufSizeM1 = sizeof ( pBuf->buf ) - 1u;
|
||||
count = ( bufSizeM1 - pBuf->rdix ) + pBuf->wtix;
|
||||
}
|
||||
else {
|
||||
count = (pBuf->wtix - pBuf->rdix) - 1u;
|
||||
count = ( pBuf->wtix - pBuf->rdix ) - 1u;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
@@ -102,11 +80,11 @@ static inline unsigned cacRingBufferReadSize (ringBuffer *pBuf)
|
||||
*/
|
||||
static inline unsigned cacRingBufferContiguousReadSize (ringBuffer *pBuf)
|
||||
{
|
||||
static const unsigned bufSizeM1 = sizeof (pBuf->buf) - 1u;
|
||||
unsigned long count;
|
||||
static const unsigned bufSizeM1 = sizeof ( pBuf->buf ) - 1u;
|
||||
unsigned long count;
|
||||
|
||||
if ( pBuf->wtix <= pBuf->rdix ) {
|
||||
if (pBuf->rdix==bufSizeM1) {
|
||||
if ( pBuf->rdix == bufSizeM1 ) {
|
||||
count = pBuf->wtix;
|
||||
}
|
||||
else {
|
||||
@@ -114,7 +92,7 @@ static inline unsigned cacRingBufferContiguousReadSize (ringBuffer *pBuf)
|
||||
}
|
||||
}
|
||||
else {
|
||||
count = (pBuf->wtix - pBuf->rdix) - 1u;
|
||||
count = ( pBuf->wtix - pBuf->rdix ) - 1u;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
@@ -122,11 +100,11 @@ static inline unsigned cacRingBufferContiguousReadSize (ringBuffer *pBuf)
|
||||
/*
|
||||
* cacRingBufferWriteSize ()
|
||||
*/
|
||||
static inline unsigned cacRingBufferWriteSize (ringBuffer *pBuf)
|
||||
static inline unsigned cacRingBufferWriteSize ( ringBuffer *pBuf )
|
||||
{
|
||||
unsigned long count;
|
||||
|
||||
if (pBuf->wtix <= pBuf->rdix) {
|
||||
if ( pBuf->wtix <= pBuf->rdix ) {
|
||||
count = pBuf->rdix - pBuf->wtix;
|
||||
}
|
||||
else {
|
||||
@@ -138,15 +116,15 @@ static inline unsigned cacRingBufferWriteSize (ringBuffer *pBuf)
|
||||
/*
|
||||
* cacRingBufferContiguousWriteSize ()
|
||||
*/
|
||||
static inline unsigned cacRingBufferContiguousWriteSize (ringBuffer *pBuf)
|
||||
static inline unsigned cacRingBufferContiguousWriteSize ( ringBuffer *pBuf )
|
||||
{
|
||||
unsigned long count;
|
||||
|
||||
if (pBuf->wtix <= pBuf->rdix) {
|
||||
if ( pBuf->wtix <= pBuf->rdix ) {
|
||||
count = pBuf->rdix - pBuf->wtix;
|
||||
}
|
||||
else {
|
||||
count = sizeof (pBuf->buf) - pBuf->wtix;
|
||||
count = sizeof ( pBuf->buf ) - pBuf->wtix;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
@@ -158,17 +136,23 @@ static inline unsigned cacRingBufferContiguousWriteSize (ringBuffer *pBuf)
|
||||
* returns the number of bytes read which may be less than
|
||||
* the number requested.
|
||||
*/
|
||||
static unsigned cacRingBufferReadPartial (ringBuffer *pRing, void *pBuf,
|
||||
unsigned nBytes)
|
||||
static unsigned cacRingBufferReadPartial ( ringBuffer *pRing, void *pBuf,
|
||||
unsigned nBytes )
|
||||
{
|
||||
unsigned totalBytes;
|
||||
|
||||
if ( pRing->wtix < pRing->rdix ) {
|
||||
static const unsigned bufSizeM1 = sizeof (pRing->buf) - 1u;
|
||||
if ( pRing->wtix <= pRing->rdix ) {
|
||||
static const unsigned bufSizeM1 = sizeof ( pRing->buf ) - 1u;
|
||||
unsigned nBytesAvail1stBlock, nBytesAvail2ndBlock;
|
||||
|
||||
nBytesAvail1stBlock = bufSizeM1 - pRing->rdix;
|
||||
nBytesAvail2ndBlock = pRing->wtix;
|
||||
if ( pRing->rdix == bufSizeM1 ) {
|
||||
nBytesAvail1stBlock = pRing->wtix;
|
||||
nBytesAvail2ndBlock = 0u;
|
||||
}
|
||||
else {
|
||||
nBytesAvail1stBlock = bufSizeM1 - pRing->rdix;
|
||||
nBytesAvail2ndBlock = pRing->wtix;
|
||||
}
|
||||
if ( nBytesAvail1stBlock >= nBytes ) {
|
||||
totalBytes = nBytes;
|
||||
memcpy ( pBuf, pRing->buf + pRing->rdix + 1u, totalBytes );
|
||||
@@ -186,53 +170,15 @@ static unsigned cacRingBufferReadPartial (ringBuffer *pRing, void *pBuf,
|
||||
pRing->rdix += totalBytes;
|
||||
pRing->rdix &= ringIndexMask;
|
||||
}
|
||||
else if ( pRing->wtix > pRing->rdix ) {
|
||||
totalBytes = (pRing->wtix - pRing->rdix) - 1;
|
||||
else {
|
||||
totalBytes = ( pRing->wtix - pRing->rdix ) - 1;
|
||||
if ( totalBytes > nBytes ) {
|
||||
totalBytes = nBytes;
|
||||
}
|
||||
memcpy (pBuf, pRing->buf+pRing->rdix+1, totalBytes);
|
||||
memcpy ( pBuf, pRing->buf+pRing->rdix+1, totalBytes );
|
||||
pRing->rdix += totalBytes;
|
||||
pRing->rdix &= ringIndexMask;
|
||||
}
|
||||
else {
|
||||
totalBytes = 0;
|
||||
}
|
||||
|
||||
return totalBytes;
|
||||
}
|
||||
|
||||
/*
|
||||
* cacRingBufferRead ()
|
||||
*
|
||||
* returns the number of bytes read which may be less than
|
||||
* the number requested.
|
||||
*/
|
||||
unsigned cacRingBufferRead (ringBuffer *pRing, void *pBuf,
|
||||
unsigned nBytes)
|
||||
{
|
||||
unsigned char *pBufTmp = (unsigned char *) pBuf;
|
||||
unsigned totalBytes = 0;
|
||||
unsigned curBytes;
|
||||
|
||||
semMutexMustTake (pRing->readLock);
|
||||
|
||||
while (totalBytes<nBytes) {
|
||||
curBytes = cacRingBufferReadPartial (pRing,
|
||||
pBufTmp+totalBytes, nBytes-totalBytes);
|
||||
if (curBytes==0) {
|
||||
semBinaryMustTake (pRing->readSignal);
|
||||
if (pRing->shutDown) {
|
||||
semMutexGive (pRing->readLock);
|
||||
return totalBytes;
|
||||
}
|
||||
}
|
||||
else {
|
||||
totalBytes += curBytes;
|
||||
}
|
||||
}
|
||||
|
||||
semMutexGive (pRing->readLock);
|
||||
|
||||
return totalBytes;
|
||||
}
|
||||
@@ -243,8 +189,8 @@ unsigned cacRingBufferRead (ringBuffer *pRing, void *pBuf,
|
||||
* returns the number of bytes written which may be less than
|
||||
* the number requested.
|
||||
*/
|
||||
static unsigned cacRingBufferWritePartial (ringBuffer *pRing,
|
||||
const void *pBuf, unsigned nBytes)
|
||||
static unsigned cacRingBufferWritePartial ( ringBuffer *pRing,
|
||||
const void *pBuf, unsigned nBytes )
|
||||
{
|
||||
unsigned totalBytes;
|
||||
|
||||
@@ -287,96 +233,37 @@ static unsigned cacRingBufferWritePartial (ringBuffer *pRing,
|
||||
return totalBytes;
|
||||
}
|
||||
|
||||
/*
|
||||
* cacRingBufferWrite ()
|
||||
*
|
||||
* returns the number of bytes written which may be less than
|
||||
* the number requested.
|
||||
*/
|
||||
unsigned cacRingBufferWrite (ringBuffer *pRing, const void *pBuf,
|
||||
unsigned nBytes)
|
||||
void cacRingBufferWriteLock ( ringBuffer *pBuf )
|
||||
{
|
||||
unsigned char *pBufTmp = (unsigned char *) pBuf;
|
||||
unsigned totalBytes = 0;
|
||||
unsigned curBytes;
|
||||
|
||||
semMutexMustTake ( pRing->writeLock );
|
||||
|
||||
while ( totalBytes < nBytes ) {
|
||||
curBytes = cacRingBufferWritePartial ( pRing,
|
||||
pBufTmp+totalBytes, nBytes-totalBytes );
|
||||
if ( curBytes == 0 ) {
|
||||
semBinaryGive ( pRing->readSignal );
|
||||
semBinaryMustTake ( pRing->writeSignal );
|
||||
if ( pRing->shutDown ) {
|
||||
semMutexGive ( pRing->writeLock );
|
||||
return totalBytes;
|
||||
}
|
||||
}
|
||||
else {
|
||||
totalBytes += curBytes;
|
||||
}
|
||||
}
|
||||
|
||||
semMutexGive ( pRing->writeLock );
|
||||
|
||||
return totalBytes;
|
||||
semMutexMustTake ( pBuf->writeLock );
|
||||
}
|
||||
|
||||
void cacRingBufferWriteLock (ringBuffer *pBuf)
|
||||
bool cacRingBufferWriteLockIfBytesAvailable ( ringBuffer *pBuf, unsigned bytesRequired )
|
||||
{
|
||||
semMutexMustTake (pBuf->writeLock);
|
||||
}
|
||||
|
||||
bool cacRingBufferWriteLockNoBlock (ringBuffer *pBuf, unsigned bytesRequired)
|
||||
{
|
||||
semMutexMustTake (pBuf->writeLock);
|
||||
semMutexMustTake ( pBuf->writeLock );
|
||||
if ( cacRingBufferWriteSize (pBuf) < bytesRequired ) {
|
||||
semMutexGive (pBuf->writeLock);
|
||||
semMutexGive ( pBuf->writeLock );
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void cacRingBufferWriteUnlock (ringBuffer *pBuf)
|
||||
void cacRingBufferWriteUnlock ( ringBuffer *pBuf )
|
||||
{
|
||||
semMutexGive (pBuf->writeLock);
|
||||
semMutexGive ( pBuf->writeLock );
|
||||
}
|
||||
|
||||
void *cacRingBufferWriteReserve (ringBuffer *pRing, unsigned *pBytesAvail)
|
||||
void *cacRingBufferWriteReserve ( ringBuffer *pRing, unsigned *pBytesAvail )
|
||||
{
|
||||
unsigned avail;
|
||||
|
||||
semMutexMustTake (pRing->writeLock);
|
||||
semMutexMustTake ( pRing->writeLock );
|
||||
|
||||
avail = cacRingBufferContiguousWriteSize (pRing);
|
||||
while (avail==0) {
|
||||
semBinaryGive (pRing->readSignal);
|
||||
semBinaryMustTake (pRing->writeSignal);
|
||||
if (pRing->shutDown) {
|
||||
semMutexGive (pRing->writeLock);
|
||||
*pBytesAvail = 0u;
|
||||
return 0;
|
||||
}
|
||||
avail = cacRingBufferContiguousWriteSize (pRing);
|
||||
}
|
||||
avail = cacRingBufferContiguousWriteSize ( pRing );
|
||||
|
||||
*pBytesAvail = avail;
|
||||
|
||||
return (void *) &pRing->buf[pRing->wtix];
|
||||
}
|
||||
|
||||
void *cacRingBufferWriteReserveNoBlock (ringBuffer *pRing, unsigned *pBytesAvail)
|
||||
{
|
||||
unsigned avail;
|
||||
|
||||
semMutexMustTake (pRing->writeLock);
|
||||
|
||||
avail = cacRingBufferContiguousWriteSize (pRing);
|
||||
|
||||
if ( avail==0 || pRing->shutDown ) {
|
||||
if ( avail == 0 ) {
|
||||
*pBytesAvail = 0u;
|
||||
semMutexGive (pRing->writeLock);
|
||||
semMutexGive ( pRing->writeLock );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -385,76 +272,113 @@ void *cacRingBufferWriteReserveNoBlock (ringBuffer *pRing, unsigned *pBytesAvail
|
||||
return (void *) &pRing->buf[pRing->wtix];
|
||||
}
|
||||
|
||||
void cacRingBufferWriteCommit (ringBuffer *pRing, unsigned delta)
|
||||
void cacRingBufferWriteCommit ( ringBuffer *pRing, unsigned delta )
|
||||
{
|
||||
pRing->wtix += delta;
|
||||
pRing->wtix &= ringIndexMask;
|
||||
semMutexGive (pRing->writeLock);
|
||||
semMutexGive ( pRing->writeLock );
|
||||
}
|
||||
|
||||
void *cacRingBufferReadReserve (ringBuffer *pRing, unsigned *pBytesAvail)
|
||||
bool cacRingBufferWriteNoBlock ( ringBuffer *pBuf, const void *pMsg, unsigned bytesRequired )
|
||||
{
|
||||
unsigned avail;
|
||||
unsigned nBytesWritten;
|
||||
|
||||
semMutexMustTake (pRing->readLock);
|
||||
|
||||
avail = cacRingBufferContiguousReadSize (pRing);
|
||||
while (avail==0) {
|
||||
semBinaryMustTake (pRing->readSignal);
|
||||
if (pRing->shutDown) {
|
||||
semMutexGive (pRing->readLock);
|
||||
*pBytesAvail = 0u;
|
||||
return NULL;
|
||||
}
|
||||
avail = cacRingBufferContiguousReadSize (pRing);
|
||||
semMutexMustTake ( pBuf->writeLock );
|
||||
if ( cacRingBufferWriteSize ( pBuf ) < bytesRequired ) {
|
||||
semMutexGive ( pBuf->writeLock );
|
||||
return false;
|
||||
}
|
||||
|
||||
*pBytesAvail = avail;
|
||||
|
||||
return (void *) &pRing->buf[(pRing->rdix+1) & ringIndexMask];
|
||||
nBytesWritten = cacRingBufferWritePartial ( pBuf, pMsg, bytesRequired );
|
||||
semMutexGive ( pBuf->writeLock );
|
||||
return nBytesWritten == bytesRequired;
|
||||
}
|
||||
|
||||
void *cacRingBufferReadReserveNoBlock (ringBuffer *pRing, unsigned *pBytesAvail)
|
||||
bool cacRingBufferWriteMultipartMessageNoBlock ( ringBuffer *pBuf,
|
||||
const msgDescriptor *pMsgs, unsigned nMsgs )
|
||||
{
|
||||
unsigned i;
|
||||
unsigned totalBytes = 0u;
|
||||
unsigned nBytesWritten;
|
||||
|
||||
for ( i = 0u; i < nMsgs; i++ ) {
|
||||
totalBytes += pMsgs[i].length;
|
||||
}
|
||||
|
||||
semMutexMustTake ( pBuf->writeLock );
|
||||
|
||||
if ( cacRingBufferWriteSize ( pBuf ) < totalBytes ) {
|
||||
semMutexGive ( pBuf->writeLock );
|
||||
return false;
|
||||
}
|
||||
|
||||
for ( i = 0u; i < nMsgs; i++ ) {
|
||||
nBytesWritten = cacRingBufferWritePartial ( pBuf,
|
||||
pMsgs[i].pMsg, pMsgs[i].length );
|
||||
if ( nBytesWritten != pMsgs[i].length ) {
|
||||
semMutexGive ( pBuf->writeLock );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
semMutexGive ( pBuf->writeLock );
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned cacRingBufferWrite ( ringBuffer *pBuf, const void *pMsg, unsigned nBytes )
|
||||
{
|
||||
unsigned nBytesWritten;
|
||||
|
||||
semMutexMustTake ( pBuf->writeLock );
|
||||
nBytesWritten = cacRingBufferWritePartial ( pBuf, pMsg, nBytes );
|
||||
semMutexGive ( pBuf->writeLock );
|
||||
|
||||
return nBytesWritten;
|
||||
}
|
||||
|
||||
void *cacRingBufferReadReserve ( ringBuffer *pRing, unsigned *pBytesAvail )
|
||||
{
|
||||
unsigned avail;
|
||||
|
||||
semMutexMustTake (pRing->readLock);
|
||||
semMutexMustTake ( pRing->readLock );
|
||||
|
||||
avail = cacRingBufferContiguousReadSize (pRing);
|
||||
avail = cacRingBufferContiguousReadSize ( pRing );
|
||||
|
||||
if ( avail==0 || pRing->shutDown ) {
|
||||
if ( avail == 0 ) {
|
||||
*pBytesAvail = 0u;
|
||||
semMutexGive (pRing->readLock);
|
||||
semMutexGive ( pRing->readLock );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*pBytesAvail = avail;
|
||||
|
||||
return (void *) &pRing->buf[(pRing->rdix+1) & ringIndexMask];
|
||||
return (void *) &pRing->buf[ ( pRing->rdix + 1 ) & ringIndexMask ];
|
||||
}
|
||||
|
||||
|
||||
void cacRingBufferReadCommit (ringBuffer *pRing, unsigned delta)
|
||||
void cacRingBufferReadCommit ( ringBuffer *pRing, unsigned delta )
|
||||
{
|
||||
pRing->rdix += delta;
|
||||
pRing->rdix &= ringIndexMask;
|
||||
semMutexGive (pRing->readLock);
|
||||
semMutexGive ( pRing->readLock );
|
||||
}
|
||||
|
||||
bool cacRingBufferWriteFlush (ringBuffer *pRing)
|
||||
bool cacRingBufferReadNoBlock ( ringBuffer *pBuf, void *pDest, unsigned nBytesRequired )
|
||||
{
|
||||
if ( cacRingBufferReadSize (pRing) ) {
|
||||
semBinaryGive (pRing->readSignal);
|
||||
return true;
|
||||
semMutexMustTake ( pBuf->readLock );
|
||||
unsigned available = cacRingBufferReadSize ( pBuf );
|
||||
if ( available < nBytesRequired) {
|
||||
semMutexGive ( pBuf->readLock );
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
char *pCurrent = static_cast <char *> ( pDest );
|
||||
unsigned totalBytes = cacRingBufferReadPartial ( pBuf, pCurrent, nBytesRequired );
|
||||
unsigned diff = nBytesRequired - totalBytes;
|
||||
if ( diff ) {
|
||||
totalBytes += cacRingBufferReadPartial ( pBuf, &pCurrent[totalBytes], diff );
|
||||
assert ( totalBytes == nBytesRequired );
|
||||
}
|
||||
semMutexGive ( pBuf->readLock );
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cacRingBufferReadFlush (ringBuffer *pRing)
|
||||
{
|
||||
if ( cacRingBufferWriteSize (pRing) ) {
|
||||
semBinaryGive (pRing->writeSignal);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
+19
-21
@@ -25,45 +25,43 @@
|
||||
#define nElementsInRing (1<<nBitsRingIndex)
|
||||
|
||||
typedef struct ringBuffer {
|
||||
semBinaryId readSignal;
|
||||
semBinaryId writeSignal;
|
||||
semMutexId readLock;
|
||||
semMutexId writeLock;
|
||||
unsigned rdix; /* index of last char read */
|
||||
unsigned wtix; /* index of next char to write */
|
||||
unsigned shutDown;
|
||||
char buf[nElementsInRing];
|
||||
} ringBuffer;
|
||||
|
||||
int cacRingBufferConstruct (ringBuffer *pBuf);
|
||||
void cacRingBufferDestroy (ringBuffer *pBuf);
|
||||
bool cacRingBufferConstruct ( ringBuffer *pBuf );
|
||||
|
||||
unsigned cacRingBufferWrite (ringBuffer *pRing,
|
||||
const void *pBuf, unsigned nBytes);
|
||||
void cacRingBufferDestroy ( ringBuffer *pBuf );
|
||||
|
||||
unsigned cacRingBufferRead (ringBuffer *pRing,
|
||||
void *pBuf, unsigned nBytes);
|
||||
void cacRingBufferWriteLock ( ringBuffer *pBuf );
|
||||
|
||||
void cacRingBufferWriteLock (ringBuffer *pBuf);
|
||||
bool cacRingBufferWriteLockIfBytesAvailable ( ringBuffer *pBuf, unsigned bytesRequired );
|
||||
|
||||
bool cacRingBufferWriteLockNoBlock (ringBuffer *pBuf, unsigned bytesRequired);
|
||||
void cacRingBufferWriteUnlock ( ringBuffer *pBuf );
|
||||
|
||||
void cacRingBufferWriteUnlock (ringBuffer *pBuf);
|
||||
unsigned cacRingBufferWrite ( ringBuffer *pBuf, const void *pMsg, unsigned nBytes );
|
||||
|
||||
void *cacRingBufferWriteReserve (ringBuffer *pBuf, unsigned *pAvailBytes);
|
||||
bool cacRingBufferWriteNoBlock ( ringBuffer *pBuf, const void *pMsg, unsigned nBytes );
|
||||
|
||||
void cacRingBufferWriteCommit (ringBuffer *pBuf, unsigned delta);
|
||||
struct msgDescriptor {
|
||||
const void *pMsg;
|
||||
unsigned length;
|
||||
};
|
||||
|
||||
void *cacRingBufferReadReserve (ringBuffer *pBuf, unsigned *pBytesAvail);
|
||||
bool cacRingBufferWriteMultipartMessageNoBlock ( ringBuffer *pBuf,
|
||||
const msgDescriptor *pMsgs, unsigned nMsgs );
|
||||
|
||||
void *cacRingBufferReadReserveNoBlock (ringBuffer *pBuf, unsigned *pBytesAvail);
|
||||
void *cacRingBufferWriteReserve ( ringBuffer *pBuf, unsigned *pBytesAvail );
|
||||
|
||||
void cacRingBufferReadCommit (ringBuffer *pBuf, unsigned delta);
|
||||
void cacRingBufferWriteCommit ( ringBuffer *pBuf, unsigned delta );
|
||||
|
||||
// return true if there was something to flush and otherwise false
|
||||
bool cacRingBufferReadFlush (ringBuffer *pBuf);
|
||||
bool cacRingBufferWriteFlush (ringBuffer *pBuf);
|
||||
void *cacRingBufferReadReserve ( ringBuffer *pBuf, unsigned *pBytesAvail );
|
||||
|
||||
void cacRingBufferShutDown (ringBuffer *pBuf);
|
||||
bool cacRingBufferReadNoBlock ( ringBuffer *pBuf, void *pDest, unsigned nBytesRequired );
|
||||
|
||||
void cacRingBufferReadCommit ( ringBuffer *pBuf, unsigned delta );
|
||||
|
||||
#endif /* ringBufferh */
|
||||
|
||||
+58
-79
@@ -28,10 +28,10 @@ searchTimer::searchTimer (udpiiu &iiuIn, osiTimerQueue &queueIn) :
|
||||
framesPerTryCongestThresh (UINT_MAX),
|
||||
minRetry (UINT_MAX),
|
||||
retry (0u),
|
||||
searchTries (0u),
|
||||
searchResponses (0u),
|
||||
searchTriesWithinThisPass (0u),
|
||||
searchResponsesWithinThisPass (0u),
|
||||
retrySeqNo (0u),
|
||||
retrySeqNoAtListBegin (0u),
|
||||
retrySeqAtPassBegin (0u),
|
||||
period (CA_RECAST_DELAY)
|
||||
{
|
||||
}
|
||||
@@ -47,7 +47,7 @@ void searchTimer::reset ( double delayToNextTry )
|
||||
delayToNextTry = CA_RECAST_DELAY;
|
||||
}
|
||||
|
||||
this->iiu.pcas->lock ();
|
||||
this->lock ();
|
||||
this->retry = 0;
|
||||
if ( this->period > delayToNextTry ) {
|
||||
reschedule = true;
|
||||
@@ -56,7 +56,7 @@ void searchTimer::reset ( double delayToNextTry )
|
||||
reschedule = false;
|
||||
}
|
||||
this->period = CA_RECAST_DELAY;
|
||||
this->iiu.pcas->unlock ();
|
||||
this->unlock ();
|
||||
|
||||
if ( reschedule ) {
|
||||
this->reschedule ( delayToNextTry );
|
||||
@@ -76,7 +76,7 @@ void searchTimer::setRetryInterval (unsigned retryNo)
|
||||
unsigned idelay;
|
||||
double delay;
|
||||
|
||||
this->iiu.pcas->lock ();
|
||||
this->lock ();
|
||||
|
||||
/*
|
||||
* set the retry number
|
||||
@@ -93,7 +93,7 @@ void searchTimer::setRetryInterval (unsigned retryNo)
|
||||
*/
|
||||
this->period = min (CA_RECAST_PERIOD, delay);
|
||||
|
||||
this->iiu.pcas->unlock ();
|
||||
this->unlock ();
|
||||
|
||||
debugPrintf ( ("new CA search period is %f sec\n", this->period) );
|
||||
}
|
||||
@@ -107,17 +107,21 @@ void searchTimer::setRetryInterval (unsigned retryNo)
|
||||
//
|
||||
void searchTimer::notifySearchResponse ( unsigned short retrySeqNo )
|
||||
{
|
||||
this->iiu.pcas->lock ();
|
||||
bool reschedualNeeded;
|
||||
|
||||
if ( this->retrySeqNoAtListBegin <= retrySeqNo ) {
|
||||
if ( this->searchResponses < ULONG_MAX ) {
|
||||
this->searchResponses++;
|
||||
this->lock ();
|
||||
|
||||
if ( this->retrySeqAtPassBegin <= retrySeqNo ) {
|
||||
if ( this->searchResponsesWithinThisPass < UINT_MAX ) {
|
||||
this->searchResponsesWithinThisPass++;
|
||||
}
|
||||
}
|
||||
|
||||
this->iiu.pcas->unlock ();
|
||||
|
||||
if ( retrySeqNo == this->retrySeqNo ) {
|
||||
reschedualNeeded = ( retrySeqNo == this->retrySeqNo );
|
||||
|
||||
this->unlock ();
|
||||
|
||||
if ( reschedualNeeded ) {
|
||||
this->reschedule (0.0);
|
||||
}
|
||||
}
|
||||
@@ -127,19 +131,17 @@ void searchTimer::notifySearchResponse ( unsigned short retrySeqNo )
|
||||
//
|
||||
void searchTimer::expire ()
|
||||
{
|
||||
tsDLIterBD <nciu> chan(0);
|
||||
tsDLIterBD <nciu> firstChan(0);
|
||||
int status;
|
||||
unsigned nSent=0u;
|
||||
|
||||
unsigned nFrameSent = 0u;
|
||||
unsigned nChanSent = 0u;
|
||||
|
||||
/*
|
||||
* check to see if there is nothing to do here
|
||||
*/
|
||||
if ( ellCount (&this->iiu.chidList) ==0 ) {
|
||||
if ( this->iiu.channelCount () == 0 ) {
|
||||
return;
|
||||
}
|
||||
|
||||
this->iiu.pcas->lock ();
|
||||
this->lock ();
|
||||
|
||||
/*
|
||||
* increment the retry sequence number
|
||||
@@ -173,8 +175,8 @@ void searchTimer::expire ()
|
||||
* increase frames per try only if we see better than
|
||||
* a 93.75% success rate for one pass through the list
|
||||
*/
|
||||
if (this->searchResponses >
|
||||
(this->searchTries-(this->searchTries/16u)) ) {
|
||||
if (this->searchResponsesWithinThisPass >
|
||||
(this->searchTriesWithinThisPass-(this->searchTriesWithinThisPass/16u)) ) {
|
||||
/*
|
||||
* increase UDP frames per try if we have a good score
|
||||
*/
|
||||
@@ -189,33 +191,26 @@ void searchTimer::expire ()
|
||||
this->framesPerTry += (this->framesPerTry/8) + 1;
|
||||
}
|
||||
debugPrintf ( ("Increasing frame count to %u t=%u r=%u\n",
|
||||
this->framesPerTry, this->searchTries, this->searchResponses) );
|
||||
this->framesPerTry, this->searchTriesWithinThisPass, this->searchResponsesWithinThisPass) );
|
||||
}
|
||||
}
|
||||
/*
|
||||
* if we detect congestion because we have less than a 87.5% success
|
||||
* rate then gradually reduce the frames per try
|
||||
*/
|
||||
else if ( this->searchResponses <
|
||||
(this->searchTries-(this->searchTries/8u)) ) {
|
||||
else if ( this->searchResponsesWithinThisPass <
|
||||
(this->searchTriesWithinThisPass-(this->searchTriesWithinThisPass/8u)) ) {
|
||||
if (this->framesPerTry>1) {
|
||||
this->framesPerTry--;
|
||||
}
|
||||
this->framesPerTryCongestThresh = this->framesPerTry/2 + 1;
|
||||
debugPrintf ( ("Congestion detected - set frames per try to %u t=%u r=%u\n",
|
||||
this->framesPerTry, this->searchTries,
|
||||
this->searchResponses) );
|
||||
this->framesPerTry, this->searchTriesWithinThisPass,
|
||||
this->searchResponsesWithinThisPass) );
|
||||
}
|
||||
|
||||
/*
|
||||
* a successful chan->searchMsg() sends channel to
|
||||
* the end of the list
|
||||
*/
|
||||
firstChan = chan = this->iiu.chidList.first ();
|
||||
while ( chan.valid () ) {
|
||||
|
||||
this->minRetry = min (this->minRetry, chan->retry);
|
||||
|
||||
while ( 1 ) {
|
||||
|
||||
/*
|
||||
* clear counter when we reach the end of the list
|
||||
*
|
||||
@@ -223,10 +218,10 @@ void searchTimer::expire ()
|
||||
* dont increase the delay between search
|
||||
* requests
|
||||
*/
|
||||
if ( this->iiu.pcas->endOfBCastList == chan ) {
|
||||
if ( this->searchResponses == 0u ) {
|
||||
if ( this->searchTriesWithinThisPass >= this->iiu.channelCount () ) {
|
||||
if ( this->searchResponsesWithinThisPass == 0u ) {
|
||||
debugPrintf ( ("increasing search try interval\n") );
|
||||
this->setRetryInterval (this->minRetry + 1u);
|
||||
this->setRetryInterval ( this->minRetry + 1u );
|
||||
}
|
||||
|
||||
this->minRetry = UINT_MAX;
|
||||
@@ -243,83 +238,67 @@ void searchTimer::expire ()
|
||||
/*
|
||||
* so that old search tries will not update the counters
|
||||
*/
|
||||
this->retrySeqNoAtListBegin = this->retrySeqNo;
|
||||
this->retrySeqAtPassBegin = this->retrySeqNo;
|
||||
|
||||
/*
|
||||
* reset the search try/response counters at the end of the list
|
||||
* (sequence number) so that we dont overflow, but dont subtract
|
||||
* out tries that dont have a matching response yet in case they
|
||||
* are delayed
|
||||
*/
|
||||
if ( this->searchTries > this->searchResponses ) {
|
||||
this->searchTries -= this->searchResponses;
|
||||
}
|
||||
else {
|
||||
this->searchTries = 0;
|
||||
}
|
||||
this->searchResponses = 0;
|
||||
this->searchTriesWithinThisPass = 0;
|
||||
this->searchResponsesWithinThisPass = 0;
|
||||
|
||||
debugPrintf ( ("saw end of list\n") );
|
||||
}
|
||||
|
||||
/*
|
||||
* this moves the channel to the end of the
|
||||
* list (if successful)
|
||||
*/
|
||||
status = chan->searchMsg ();
|
||||
if ( status != ECA_NORMAL ) {
|
||||
nSent++;
|
||||
unsigned retryNoForThisChannel;
|
||||
if ( ! this->iiu.searchMsg ( this->retrySeqNo, retryNoForThisChannel ) ) {
|
||||
nFrameSent++;
|
||||
|
||||
if ( nSent >= this->framesPerTry ) {
|
||||
if ( nFrameSent >= this->framesPerTry ) {
|
||||
break;
|
||||
}
|
||||
|
||||
// flush out the search request buffer
|
||||
this->iiu.flush ();
|
||||
|
||||
// try again
|
||||
status = chan->searchMsg ();
|
||||
if (status != ECA_NORMAL) {
|
||||
if ( ! this->iiu.searchMsg ( this->retrySeqNo, retryNoForThisChannel ) ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( this->searchTries < ULONG_MAX ) {
|
||||
this->searchTries++;
|
||||
}
|
||||
this->minRetry = min ( this->minRetry, retryNoForThisChannel );
|
||||
|
||||
chan->retrySeqNo = this->retrySeqNo;
|
||||
chan = this->iiu.chidList.first ();
|
||||
if ( this->searchTriesWithinThisPass < UINT_MAX ) {
|
||||
this->searchTriesWithinThisPass++;
|
||||
}
|
||||
if ( nChanSent < UINT_MAX ) {
|
||||
nChanSent++;
|
||||
}
|
||||
|
||||
/*
|
||||
* dont send any of the channels twice within one try
|
||||
*/
|
||||
if ( chan == firstChan ) {
|
||||
if ( nChanSent >= this->iiu.channelCount () ) {
|
||||
/*
|
||||
* add one to nSent because there may be
|
||||
* add one to nFrameSent because there may be
|
||||
* one more partial frame to be sent
|
||||
*/
|
||||
nSent++;
|
||||
nFrameSent++;
|
||||
|
||||
/*
|
||||
* cap this->framesPerTry to
|
||||
* the number of frames required for all of
|
||||
* the unresolved channels
|
||||
*/
|
||||
if (this->framesPerTry>nSent) {
|
||||
this->framesPerTry = nSent;
|
||||
if ( this->framesPerTry > nFrameSent ) {
|
||||
this->framesPerTry = nFrameSent;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
this->iiu.pcas->unlock ();
|
||||
this->unlock ();
|
||||
|
||||
// flush out the search request buffer
|
||||
this->iiu.flush ();
|
||||
|
||||
debugPrintf ( ("sent %u delay sec=%f\n", nSent, this->period) );
|
||||
debugPrintf ( ("sent %u delay sec=%f\n", nFrameSent, this->period) );
|
||||
}
|
||||
|
||||
void searchTimer::destroy ()
|
||||
@@ -328,7 +307,7 @@ void searchTimer::destroy ()
|
||||
|
||||
bool searchTimer::again () const
|
||||
{
|
||||
if ( ellCount (&this->iiu.chidList) == 0 ) {
|
||||
if ( this->iiu.channelCount () == 0 ) {
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -29,14 +29,7 @@ tcpRecvWatchdog::~tcpRecvWatchdog ()
|
||||
|
||||
void tcpRecvWatchdog::expire ()
|
||||
{
|
||||
/*
|
||||
* remain backwards compatible with old servers
|
||||
* ( this isnt an echo request )
|
||||
*/
|
||||
if ( ! this->echoProtocolAccepted ) {
|
||||
this->noopRequestMsg ();
|
||||
}
|
||||
else if ( this->responsePending ) {
|
||||
if ( this->responsePending ) {
|
||||
char hostName[128];
|
||||
this->hostName ( hostName, sizeof (hostName) );
|
||||
ca_printf ( "CA server %s unresponsive for %g sec. Disconnecting.\n",
|
||||
@@ -44,8 +37,10 @@ void tcpRecvWatchdog::expire ()
|
||||
this->shutdown ();
|
||||
}
|
||||
else {
|
||||
this->echoRequestMsg ();
|
||||
this->responsePending = true;
|
||||
this->echoRequest ();
|
||||
if ( this->echoProtocolAccepted ) {
|
||||
this->responsePending = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+573
-979
File diff suppressed because it is too large
Load Diff
+38
-24
@@ -18,7 +18,7 @@
|
||||
|
||||
inline osiSockAddr tcpiiu::address () const
|
||||
{
|
||||
return this->dest;
|
||||
return this->ipToA.address ();
|
||||
}
|
||||
|
||||
inline void * tcpiiu::operator new (size_t size)
|
||||
@@ -33,41 +33,55 @@ inline void tcpiiu::operator delete (void *pCadaver, size_t size)
|
||||
|
||||
inline bool tcpiiu::fullyConstructed () const
|
||||
{
|
||||
return this->fc;
|
||||
}
|
||||
|
||||
inline void tcpiiu::flush ()
|
||||
{
|
||||
if ( cacRingBufferWriteFlush ( &this->send ) ) {
|
||||
this->armSendWatchdog ();
|
||||
}
|
||||
return this->fullyConstructedFlag;
|
||||
}
|
||||
|
||||
inline void tcpiiu::hostName ( char *pBuf, unsigned bufLength ) const
|
||||
{
|
||||
if ( bufLength ) {
|
||||
strncpy ( pBuf, this->host_name_str, bufLength );
|
||||
pBuf[bufLength - 1u] = '\0';
|
||||
}
|
||||
this->ipToA.hostName ( pBuf, bufLength );
|
||||
}
|
||||
|
||||
// deprecated - please dont use
|
||||
inline const char * tcpiiu::pHostName () const
|
||||
{
|
||||
return this->host_name_str;
|
||||
}
|
||||
|
||||
inline bool tcpiiu::ca_v42_ok () const
|
||||
{
|
||||
return CA_V42 (CA_PROTOCOL_VERSION, this->minor_version_number);
|
||||
}
|
||||
|
||||
inline bool tcpiiu::ca_v41_ok () const
|
||||
{
|
||||
return CA_V41 (CA_PROTOCOL_VERSION, this->minor_version_number);
|
||||
static char nameBuf [128];
|
||||
this->ipToA.hostName ( nameBuf, sizeof ( nameBuf ) );
|
||||
return nameBuf; // ouch !!
|
||||
}
|
||||
|
||||
inline SOCKET tcpiiu::getSock () const
|
||||
{
|
||||
return this->sock;
|
||||
}
|
||||
|
||||
inline void tcpiiu::flush ()
|
||||
{
|
||||
this->flushPending = true;
|
||||
semBinaryGive ( this->sendThreadFlushSignal );
|
||||
}
|
||||
|
||||
inline bool tcpiiu::ca_v44_ok () const
|
||||
{
|
||||
return CA_V44 ( CA_PROTOCOL_VERSION, this->minor_version_number );
|
||||
}
|
||||
|
||||
inline bool tcpiiu::ca_v42_ok () const
|
||||
{
|
||||
return CA_V42 ( CA_PROTOCOL_VERSION, this->minor_version_number );
|
||||
}
|
||||
|
||||
inline bool tcpiiu::ca_v41_ok () const
|
||||
{
|
||||
return CA_V41 ( CA_PROTOCOL_VERSION, this->minor_version_number );
|
||||
}
|
||||
|
||||
inline bool tcpiiu::alive () const
|
||||
{
|
||||
if ( this->state == iiu_connecting ||
|
||||
this->state == iiu_connected ) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
+203
-344
@@ -15,9 +15,43 @@
|
||||
#include "iocinf.h"
|
||||
#include "addrList.h"
|
||||
#include "inetAddrID_IL.h"
|
||||
#include "netiiu_IL.h"
|
||||
|
||||
typedef void (*pProtoStubUDP) (udpiiu *piiu, caHdr *pMsg, const struct sockaddr_in *pnet_addr);
|
||||
|
||||
// UDP protocol dispatch table
|
||||
const udpiiu::pProtoStubUDP udpiiu::udpJumpTableCAC[] =
|
||||
{
|
||||
udpiiu::noopAction,
|
||||
udpiiu::badUDPRespAction,
|
||||
udpiiu::badUDPRespAction,
|
||||
udpiiu::badUDPRespAction,
|
||||
udpiiu::badUDPRespAction,
|
||||
udpiiu::badUDPRespAction,
|
||||
udpiiu::searchRespAction,
|
||||
udpiiu::badUDPRespAction,
|
||||
udpiiu::badUDPRespAction,
|
||||
udpiiu::badUDPRespAction,
|
||||
udpiiu::badUDPRespAction,
|
||||
udpiiu::exceptionRespAction,
|
||||
udpiiu::badUDPRespAction,
|
||||
udpiiu::beaconAction,
|
||||
udpiiu::notHereRespAction,
|
||||
udpiiu::badUDPRespAction,
|
||||
udpiiu::badUDPRespAction,
|
||||
udpiiu::repeaterAckAction,
|
||||
udpiiu::badUDPRespAction,
|
||||
udpiiu::badUDPRespAction,
|
||||
udpiiu::badUDPRespAction,
|
||||
udpiiu::badUDPRespAction,
|
||||
udpiiu::badUDPRespAction,
|
||||
udpiiu::badUDPRespAction,
|
||||
udpiiu::badUDPRespAction,
|
||||
udpiiu::badUDPRespAction,
|
||||
udpiiu::badUDPRespAction,
|
||||
udpiiu::badUDPRespAction
|
||||
};
|
||||
|
||||
//
|
||||
// udpiiu::recvMsg ()
|
||||
//
|
||||
@@ -62,12 +96,12 @@ void udpiiu::recvMsg ()
|
||||
SOCKERRSTR (errnoCpy) );
|
||||
}
|
||||
else if (status > 0) {
|
||||
status = this->post_msg ( &src.ia,
|
||||
status = this->postMsg ( src,
|
||||
this->recvBuf, (unsigned long) status );
|
||||
if ( status != ECA_NORMAL ) {
|
||||
char buf[64];
|
||||
|
||||
ipAddrToA (&src.ia, buf, sizeof(buf));
|
||||
sockAddrToA ( &src.sa, buf, sizeof (buf) );
|
||||
|
||||
ca_printf (
|
||||
"%s: bad UDP msg from %s because \"%s\"\n", __FILE__,
|
||||
@@ -210,27 +244,27 @@ void udpiiu::repeaterRegistrationMessage ( unsigned attemptNumber )
|
||||
*
|
||||
* 072392 - problem solved by using SO_REUSEADDR
|
||||
*/
|
||||
int repeater_installed (udpiiu *piiu)
|
||||
bool udpiiu::repeaterInstalled ()
|
||||
{
|
||||
int installed = FALSE;
|
||||
bool installed = false;
|
||||
int status;
|
||||
SOCKET sock;
|
||||
struct sockaddr_in bd;
|
||||
int flag;
|
||||
|
||||
sock = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||
if (sock == INVALID_SOCKET) {
|
||||
sock = socket ( AF_INET, SOCK_DGRAM, IPPROTO_UDP );
|
||||
if ( sock == INVALID_SOCKET ) {
|
||||
return installed;
|
||||
}
|
||||
|
||||
memset ( (char *) &bd, 0, sizeof (bd) );
|
||||
memset ( (char *) &bd, 0, sizeof ( bd ) );
|
||||
bd.sin_family = AF_INET;
|
||||
bd.sin_addr.s_addr = htonl (INADDR_ANY);
|
||||
bd.sin_port = htons (piiu->repeaterPort);
|
||||
status = bind (sock, (struct sockaddr *) &bd, sizeof(bd) );
|
||||
if (status<0) {
|
||||
if (SOCKERRNO == SOCK_EADDRINUSE) {
|
||||
installed = TRUE;
|
||||
bd.sin_addr.s_addr = htonl ( INADDR_ANY );
|
||||
bd.sin_port = htons ( this->repeaterPort );
|
||||
status = bind ( sock, (struct sockaddr *) &bd, sizeof ( bd ) );
|
||||
if ( status < 0 ) {
|
||||
if ( SOCKERRNO == SOCK_EADDRINUSE ) {
|
||||
installed = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -240,12 +274,12 @@ int repeater_installed (udpiiu *piiu)
|
||||
*/
|
||||
flag = TRUE;
|
||||
status = setsockopt ( sock, SOL_SOCKET, SO_REUSEADDR,
|
||||
(char *)&flag, sizeof (flag) );
|
||||
(char *)&flag, sizeof ( flag ) );
|
||||
if (status<0) {
|
||||
ca_printf ( "CAC: set socket option reuseaddr set failed\n");
|
||||
}
|
||||
|
||||
socket_close (sock);
|
||||
socket_close ( sock );
|
||||
|
||||
return installed;
|
||||
}
|
||||
@@ -253,9 +287,8 @@ int repeater_installed (udpiiu *piiu)
|
||||
//
|
||||
// udpiiu::udpiiu ()
|
||||
//
|
||||
udpiiu::udpiiu ( cac *pcac ) :
|
||||
netiiu ( pcac ),
|
||||
shutdownCmd ( false )
|
||||
udpiiu::udpiiu ( cac &cac ) :
|
||||
netiiu ( cac ), shutdownCmd ( false )
|
||||
{
|
||||
static const unsigned short PORT_ANY = 0u;
|
||||
osiSockAddr addr;
|
||||
@@ -265,8 +298,11 @@ udpiiu::udpiiu ( cac *pcac ) :
|
||||
this->repeaterPort =
|
||||
envGetInetPortConfigParam (&EPICS_CA_REPEATER_PORT, CA_REPEATER_PORT);
|
||||
|
||||
this->sock = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||
if (this->sock == INVALID_SOCKET) {
|
||||
this->serverPort =
|
||||
envGetInetPortConfigParam ( &EPICS_CA_SERVER_PORT, CA_SERVER_PORT );
|
||||
|
||||
this->sock = socket ( AF_INET, SOCK_DGRAM, IPPROTO_UDP );
|
||||
if ( this->sock == INVALID_SOCKET ) {
|
||||
ca_printf ("CAC: unable to create datagram socket because = \"%s\"\n",
|
||||
SOCKERRSTR (SOCKERRNO));
|
||||
throwWithLocation ( noSocket () );
|
||||
@@ -306,7 +342,7 @@ udpiiu::udpiiu ( cac *pcac ) :
|
||||
addr.ia.sin_addr.s_addr = htonl (INADDR_ANY);
|
||||
addr.ia.sin_port = htons (PORT_ANY);
|
||||
status = bind (this->sock, &addr.sa, sizeof (addr) );
|
||||
if (status<0) {
|
||||
if ( status < 0 ) {
|
||||
socket_close (this->sock);
|
||||
ca_printf ("CAC: unable to bind to an unconstrained address because = \"%s\"\n",
|
||||
SOCKERRSTR (SOCKERRNO));
|
||||
@@ -315,16 +351,9 @@ udpiiu::udpiiu ( cac *pcac ) :
|
||||
|
||||
this->nBytesInXmitBuf = 0u;
|
||||
|
||||
this->xmitBufLock = semMutexCreate ();
|
||||
if (!this->xmitBufLock) {
|
||||
socket_close (this->sock);
|
||||
throwWithLocation ( noMemory () );
|
||||
}
|
||||
|
||||
this->recvThreadExitSignal = semBinaryCreate (semEmpty);
|
||||
this->recvThreadExitSignal = semBinaryCreate ( semEmpty );
|
||||
if ( ! this->recvThreadExitSignal ) {
|
||||
semMutexDestroy (this->xmitBufLock);
|
||||
socket_close (this->sock);
|
||||
socket_close ( this->sock );
|
||||
throwWithLocation ( noMemory () );
|
||||
}
|
||||
|
||||
@@ -333,9 +362,9 @@ udpiiu::udpiiu ( cac *pcac ) :
|
||||
* broadcast address list
|
||||
*/
|
||||
ellInit ( &this->dest );
|
||||
configureChannelAccessAddressList (&this->dest, this->sock, pcac->ca_server_port);
|
||||
configureChannelAccessAddressList ( &this->dest, this->sock, this->serverPort );
|
||||
if ( ellCount ( &this->dest ) == 0 ) {
|
||||
genLocalExcep ( this->pcas, ECA_NOSEARCHADDR, NULL );
|
||||
genLocalExcep ( this->clientCtx (), ECA_NOSEARCHADDR, NULL );
|
||||
}
|
||||
|
||||
{
|
||||
@@ -349,18 +378,17 @@ udpiiu::udpiiu ( cac *pcac ) :
|
||||
priorityOfRecv = priorityOfSelf;
|
||||
}
|
||||
|
||||
tid = threadCreate ("CAC-UDP", priorityOfRecv,
|
||||
threadGetStackSize (threadStackMedium), cacRecvThreadUDP, this);
|
||||
tid = threadCreate ( "CAC-UDP", priorityOfRecv,
|
||||
threadGetStackSize (threadStackMedium), cacRecvThreadUDP, this );
|
||||
if (tid==0) {
|
||||
ca_printf ("CA: unable to create UDP receive thread\n");
|
||||
semBinaryDestroy (this->recvThreadExitSignal);
|
||||
semMutexDestroy (this->xmitBufLock);
|
||||
socket_close (this->sock);
|
||||
throwWithLocation ( noMemory () );
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! repeater_installed (this) ) {
|
||||
if ( ! this->repeaterInstalled () ) {
|
||||
osiSpawnDetachedProcessReturn osptr;
|
||||
|
||||
/*
|
||||
@@ -369,7 +397,7 @@ udpiiu::udpiiu ( cac *pcac ) :
|
||||
* the 2nd repeater exits when unable to attach to the
|
||||
* repeater's port)
|
||||
*/
|
||||
osptr = osiSpawnDetachedProcess ("CA Repeater", "caRepeater");
|
||||
osptr = osiSpawnDetachedProcess ( "CA Repeater", "caRepeater" );
|
||||
if ( osptr == osiSpawnDetachedProcessNoSupport ) {
|
||||
threadId tid;
|
||||
|
||||
@@ -390,28 +418,22 @@ udpiiu::udpiiu ( cac *pcac ) :
|
||||
*/
|
||||
udpiiu::~udpiiu ()
|
||||
{
|
||||
nciu *pChan, *pNext;
|
||||
|
||||
// closes the udp socket
|
||||
this->shutdown ();
|
||||
|
||||
this->pcas->lock ();
|
||||
tsDLIter <nciu> iter (this->chidList);
|
||||
pChan = iter ();
|
||||
while (pChan) {
|
||||
pNext = iter ();
|
||||
pChan->destroy ();
|
||||
pChan = pNext;
|
||||
}
|
||||
this->pcas->unlock ();
|
||||
this->detachAllChan ();
|
||||
|
||||
// wait for recv threads to exit
|
||||
semBinaryMustTake (this->recvThreadExitSignal);
|
||||
semBinaryMustTake ( this->recvThreadExitSignal );
|
||||
|
||||
semMutexDestroy (this->xmitBufLock);
|
||||
semBinaryDestroy (this->recvThreadExitSignal);
|
||||
semBinaryDestroy ( this->recvThreadExitSignal );
|
||||
|
||||
ellFree (&this->dest);
|
||||
ellFree ( &this->dest );
|
||||
|
||||
if ( this->sock != INVALID_SOCKET ) {
|
||||
socket_close ( this->sock );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -419,62 +441,72 @@ udpiiu::~udpiiu ()
|
||||
*/
|
||||
void udpiiu::shutdown ()
|
||||
{
|
||||
this->pcas->lock ();
|
||||
if ( ! this->shutdownCmd ) {
|
||||
int status;
|
||||
bool laborRequired;
|
||||
|
||||
// this knocks the UDP input thread out of recv ()
|
||||
this->lock ();
|
||||
if ( ! this->shutdownCmd ) {
|
||||
this->shutdownCmd = true;
|
||||
status = socket_close ( this->sock );
|
||||
if ( status ) {
|
||||
errlogPrintf ( "CAC UDP socket close error was \"%s\"\n",
|
||||
SOCKERRSTR (SOCKERRNO) );
|
||||
laborRequired = true;
|
||||
}
|
||||
else {
|
||||
laborRequired = false;
|
||||
}
|
||||
this->unlock ();
|
||||
|
||||
if ( laborRequired ) {
|
||||
int status;
|
||||
osiSockAddr addr;
|
||||
int size = sizeof ( addr.sa );
|
||||
|
||||
status = getsockname ( this->sock, &addr.sa, &size );
|
||||
if ( status < 0 ) {
|
||||
// this knocks the UDP input thread out of recv ()
|
||||
// on all os except linux
|
||||
socket_close ( this->sock );
|
||||
this->sock = INVALID_SOCKET;
|
||||
}
|
||||
else {
|
||||
caHdr msg;
|
||||
msg.m_cmmd = htons ( CA_PROTO_NOOP );
|
||||
msg.m_available = htonl ( 0u );
|
||||
msg.m_dataType = htons ( 0u );
|
||||
msg.m_count = htons ( 0u );
|
||||
msg.m_cid = htonl ( 0u );
|
||||
msg.m_postsize = htons ( 0u );
|
||||
|
||||
// send a wakeup msg so the UDP recv thread will exit
|
||||
status = sendto ( this->sock, reinterpret_cast < const char * > ( &msg ), sizeof (msg), 0,
|
||||
&addr.sa, sizeof ( addr.sa ) );
|
||||
if ( status < 0 ) {
|
||||
// this knocks the UDP input thread out of recv ()
|
||||
// on all os except linux
|
||||
socket_close ( this->sock );
|
||||
this->sock = INVALID_SOCKET;
|
||||
}
|
||||
}
|
||||
}
|
||||
this->pcas->unlock ();
|
||||
}
|
||||
|
||||
/*
|
||||
* bad_udp_resp_action ()
|
||||
*/
|
||||
LOCAL void bad_udp_resp_action (udpiiu * /* piiu */,
|
||||
caHdr *pMsg, const struct sockaddr_in *pnet_addr)
|
||||
void udpiiu::badUDPRespAction ( const caHdr &msg, const osiSockAddr &netAddr )
|
||||
{
|
||||
char buf[256];
|
||||
ipAddrToA ( pnet_addr, buf, sizeof (buf) );
|
||||
sockAddrToA ( &netAddr.sa, buf, sizeof ( buf ) );
|
||||
ca_printf ( "CAC: Bad response code in UDP message from %s was %u\n",
|
||||
buf, pMsg->m_cmmd);
|
||||
buf, msg.m_cmmd);
|
||||
}
|
||||
|
||||
/*
|
||||
* udp_noop_action ()
|
||||
*/
|
||||
LOCAL void udp_noop_action (udpiiu * /* piiu */, caHdr * /* pMsg */,
|
||||
const struct sockaddr_in * /* pnet_addr */)
|
||||
void udpiiu::noopAction ( const caHdr &, const osiSockAddr & )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* search_resp_action ()
|
||||
*/
|
||||
LOCAL void search_resp_action (udpiiu *piiu, caHdr *pMsg, const struct sockaddr_in *pnet_addr)
|
||||
void udpiiu::searchRespAction ( const caHdr &msg, const osiSockAddr &addr )
|
||||
{
|
||||
struct sockaddr_in ina;
|
||||
nciu *chan;
|
||||
tcpiiu *allocpiiu;
|
||||
unsigned short *pMinorVersion;
|
||||
unsigned minorVersion;
|
||||
osiSockAddr serverAddr;
|
||||
unsigned minorVersion;
|
||||
ca_uint16_t *pMinorVersion;
|
||||
|
||||
/*
|
||||
* ignore broadcast replies for deleted channels
|
||||
*
|
||||
* lock required around use of the sprintf buffer
|
||||
*/
|
||||
piiu->pcas->lock ();
|
||||
chan = piiu->pcas->lookupChan (pMsg->m_available);
|
||||
if ( ! chan ) {
|
||||
piiu->pcas->unlock ();
|
||||
if ( addr.sa.sa_family != AF_INET ) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -483,9 +515,9 @@ LOCAL void search_resp_action (udpiiu *piiu, caHdr *pMsg, const struct sockaddr_
|
||||
* is appended to the end of each search reply.
|
||||
* This value is ignored by earlier clients.
|
||||
*/
|
||||
if ( pMsg->m_postsize >= sizeof (*pMinorVersion) ){
|
||||
pMinorVersion = (unsigned short *) (pMsg+1);
|
||||
minorVersion = ntohs (*pMinorVersion);
|
||||
if ( msg.m_postsize >= sizeof (*pMinorVersion) ){
|
||||
pMinorVersion = (ca_uint16_t *) ( &msg + 1 );
|
||||
minorVersion = ntohs ( *pMinorVersion );
|
||||
}
|
||||
else {
|
||||
minorVersion = CA_UKN_MINOR_VERSION;
|
||||
@@ -495,109 +527,49 @@ LOCAL void search_resp_action (udpiiu *piiu, caHdr *pMsg, const struct sockaddr_
|
||||
* the type field is abused to carry the port number
|
||||
* so that we can have multiple servers on one host
|
||||
*/
|
||||
ina.sin_family = AF_INET;
|
||||
serverAddr.ia.sin_family = AF_INET;
|
||||
if ( CA_V48 (CA_PROTOCOL_VERSION,minorVersion) ) {
|
||||
if ( pMsg->m_cid != INADDR_BROADCAST ) {
|
||||
if ( msg.m_cid != INADDR_BROADCAST ) {
|
||||
/*
|
||||
* Leave address in network byte order (m_cid has not been
|
||||
* converted to the local byte order)
|
||||
*/
|
||||
ina.sin_addr.s_addr = pMsg->m_cid;
|
||||
serverAddr.ia.sin_addr.s_addr = msg.m_cid;
|
||||
}
|
||||
else {
|
||||
ina.sin_addr = pnet_addr->sin_addr;
|
||||
serverAddr.ia.sin_addr = addr.ia.sin_addr;
|
||||
}
|
||||
ina.sin_port = htons (pMsg->m_dataType);
|
||||
serverAddr.ia.sin_port = htons (msg.m_dataType);
|
||||
}
|
||||
else if ( CA_V45 (CA_PROTOCOL_VERSION,minorVersion) ) {
|
||||
ina.sin_port = htons (pMsg->m_dataType);
|
||||
ina.sin_addr = pnet_addr->sin_addr;
|
||||
serverAddr.ia.sin_port = htons ( msg.m_dataType );
|
||||
serverAddr.ia.sin_addr = addr.ia.sin_addr;
|
||||
}
|
||||
else {
|
||||
ina.sin_port = htons (piiu->pcas->ca_server_port);
|
||||
ina.sin_addr = pnet_addr->sin_addr;
|
||||
serverAddr.ia.sin_port = htons ( this->serverPort );
|
||||
serverAddr.ia.sin_addr = addr.ia.sin_addr;
|
||||
}
|
||||
|
||||
/*
|
||||
* Ignore duplicate search replies
|
||||
*/
|
||||
if ( chan->piiu->compareIfTCP (*chan, *pnet_addr) ) {
|
||||
piiu->pcas->unlock ();
|
||||
return;
|
||||
}
|
||||
|
||||
allocpiiu = constructTCPIIU (piiu->pcas, &ina, minorVersion);
|
||||
if ( ! allocpiiu ) {
|
||||
piiu->pcas->unlock ();
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* If this is the first channel to be
|
||||
* added to this niiu then communicate
|
||||
* the client's name to the server.
|
||||
* (CA V4.1 or higher)
|
||||
*/
|
||||
if ( ellCount ( &allocpiiu->chidList ) == 0 ) {
|
||||
allocpiiu->userNameSetMsg ();
|
||||
allocpiiu->hostNameSetMsg ();
|
||||
}
|
||||
|
||||
piiu->pcas->notifySearchResponse ( chan->retrySeqNo );
|
||||
|
||||
/*
|
||||
* Assume that we have access once connected briefly
|
||||
* until the server is able to tell us the correct
|
||||
* state for backwards compatibility.
|
||||
*
|
||||
* Their access rights call back does not get
|
||||
* called for the first time until the information
|
||||
* arrives however.
|
||||
*/
|
||||
chan->ar.read_access = TRUE;
|
||||
chan->ar.write_access = TRUE;
|
||||
|
||||
/*
|
||||
* remove it from the broadcast niiu
|
||||
*/
|
||||
chan->piiu->removeFromChanList ( *chan );
|
||||
|
||||
/*
|
||||
* chan->piiu must be correctly set prior to issuing the
|
||||
* claim request
|
||||
*
|
||||
* add to the beginning of the list until we
|
||||
* have sent the claim message (after which we
|
||||
* move it to the end of the list)
|
||||
*
|
||||
* claim pending flag is set here
|
||||
*/
|
||||
allocpiiu->addToChanList ( *chan );
|
||||
|
||||
if ( CA_V42 ( CA_PROTOCOL_VERSION, minorVersion ) ) {
|
||||
chan->searchReplySetUp ( pMsg->m_cid, USHRT_MAX, 0 );
|
||||
this->clientCtx ().lookupChannelAndTransferToTCP
|
||||
( msg.m_available, msg.m_cid, USHRT_MAX, 0,
|
||||
minorVersion, serverAddr );
|
||||
}
|
||||
else {
|
||||
chan->searchReplySetUp ( pMsg->m_cid, pMsg->m_dataType, pMsg->m_count );
|
||||
this->clientCtx ().lookupChannelAndTransferToTCP
|
||||
( msg.m_available, msg.m_cid, msg.m_dataType,
|
||||
minorVersion, msg.m_count, serverAddr );
|
||||
}
|
||||
|
||||
chan->claimMsg ( allocpiiu );
|
||||
cacRingBufferWriteFlush ( &allocpiiu->send );
|
||||
|
||||
piiu->pcas->unlock ();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* beacon_action ()
|
||||
*/
|
||||
LOCAL void beacon_action ( udpiiu * piiu,
|
||||
caHdr *pMsg, const struct sockaddr_in *pnet_addr)
|
||||
void udpiiu::beaconAction ( const caHdr &msg, const osiSockAddr &net_addr )
|
||||
{
|
||||
struct sockaddr_in ina;
|
||||
|
||||
piiu->pcas->lock ();
|
||||
|
||||
if ( net_addr.sa.sa_family != AF_INET ) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* this allows a fan-out server to potentially
|
||||
* insert the true address of the CA server
|
||||
@@ -613,143 +585,96 @@ LOCAL void beacon_action ( udpiiu * piiu,
|
||||
* then it is the overriding IP address of the server.
|
||||
*/
|
||||
ina.sin_family = AF_INET;
|
||||
if ( pMsg->m_available != htonl (INADDR_ANY) ) {
|
||||
ina.sin_addr.s_addr = pMsg->m_available;
|
||||
if ( msg.m_available != htonl (INADDR_ANY) ) {
|
||||
ina.sin_addr.s_addr = msg.m_available;
|
||||
}
|
||||
else {
|
||||
ina.sin_addr = pnet_addr->sin_addr;
|
||||
ina.sin_addr = net_addr.ia.sin_addr;
|
||||
}
|
||||
if ( pMsg->m_count != 0 ) {
|
||||
ina.sin_port = htons ( pMsg->m_count );
|
||||
if ( msg.m_count != 0 ) {
|
||||
ina.sin_port = htons ( msg.m_count );
|
||||
}
|
||||
else {
|
||||
/*
|
||||
* old servers dont supply this and the
|
||||
* default port must be assumed
|
||||
*/
|
||||
ina.sin_port = htons (piiu->pcas->ca_server_port);
|
||||
ina.sin_port = htons ( this->serverPort );
|
||||
}
|
||||
piiu->pcas->beaconNotify (ina);
|
||||
|
||||
piiu->pcas->unlock ();
|
||||
this->clientCtx ().beaconNotify ( ina );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* repeater_ack_action ()
|
||||
*/
|
||||
LOCAL void repeater_ack_action (udpiiu * piiu,
|
||||
caHdr * /* pMsg */, const struct sockaddr_in * /* pnet_addr */)
|
||||
void udpiiu::repeaterAckAction ( const caHdr &, const osiSockAddr &)
|
||||
{
|
||||
piiu->pcas->repeaterSubscribeConfirmNotify ();
|
||||
this->clientCtx ().repeaterSubscribeConfirmNotify ();
|
||||
}
|
||||
|
||||
/*
|
||||
* not_here_resp_action ()
|
||||
*/
|
||||
LOCAL void not_here_resp_action (udpiiu * /* piiu */, caHdr * /* pMsg */, const struct sockaddr_in * /* pnet_addr */)
|
||||
void udpiiu::notHereRespAction ( const caHdr &, const osiSockAddr &)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* udp_exception_resp_action ()
|
||||
*/
|
||||
LOCAL void udp_exception_resp_action ( udpiiu *piiu,
|
||||
caHdr *pMsg, const struct sockaddr_in *pnet_addr )
|
||||
void udpiiu::exceptionRespAction ( const caHdr &msg, const osiSockAddr &net_addr )
|
||||
{
|
||||
caHdr *pReqMsg = pMsg + 1;
|
||||
const caHdr &reqMsg = * ( &msg + 1 );
|
||||
char name[64];
|
||||
|
||||
ipAddrToA ( pnet_addr, name, sizeof ( name ) );
|
||||
sockAddrToA ( &net_addr.sa, name, sizeof ( name ) );
|
||||
|
||||
if ( pMsg->m_postsize > sizeof (caHdr) ){
|
||||
if ( msg.m_postsize > sizeof ( caHdr ) ){
|
||||
errlogPrintf ( "error condition \"%s\" detected by %s with context \"%s\"\n",
|
||||
ca_message ( ntohl ( pMsg->m_available ) ),
|
||||
name, reinterpret_cast <char *> ( pReqMsg + 1 ) );
|
||||
ca_message ( msg.m_available ),
|
||||
name, reinterpret_cast <const char *> ( &reqMsg + 1 ) );
|
||||
}
|
||||
else{
|
||||
errlogPrintf ( "error condition \"%s\" detected by %s\n",
|
||||
ca_message ( ntohl ( pMsg->m_available ) ), name );
|
||||
ca_message ( msg.m_available ), name );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* UDP protocol jump table
|
||||
*/
|
||||
LOCAL const pProtoStubUDP udpJumpTableCAC[] =
|
||||
{
|
||||
udp_noop_action,
|
||||
bad_udp_resp_action,
|
||||
bad_udp_resp_action,
|
||||
bad_udp_resp_action,
|
||||
bad_udp_resp_action,
|
||||
bad_udp_resp_action,
|
||||
search_resp_action,
|
||||
bad_udp_resp_action,
|
||||
bad_udp_resp_action,
|
||||
bad_udp_resp_action,
|
||||
bad_udp_resp_action,
|
||||
udp_exception_resp_action,
|
||||
bad_udp_resp_action,
|
||||
beacon_action,
|
||||
not_here_resp_action,
|
||||
bad_udp_resp_action,
|
||||
bad_udp_resp_action,
|
||||
repeater_ack_action,
|
||||
bad_udp_resp_action,
|
||||
bad_udp_resp_action,
|
||||
bad_udp_resp_action,
|
||||
bad_udp_resp_action,
|
||||
bad_udp_resp_action,
|
||||
bad_udp_resp_action,
|
||||
bad_udp_resp_action,
|
||||
bad_udp_resp_action,
|
||||
bad_udp_resp_action,
|
||||
bad_udp_resp_action
|
||||
};
|
||||
|
||||
/*
|
||||
* post_udp_msg ()
|
||||
*/
|
||||
int udpiiu::post_msg (const struct sockaddr_in *pnet_addr,
|
||||
char *pInBuf, unsigned long blockSize)
|
||||
int udpiiu::postMsg ( const osiSockAddr &net_addr,
|
||||
char *pInBuf, unsigned long blockSize )
|
||||
{
|
||||
caHdr *pCurMsg;
|
||||
|
||||
while ( blockSize ) {
|
||||
unsigned long size;
|
||||
|
||||
if ( blockSize < sizeof (*pCurMsg) ) {
|
||||
if ( blockSize < sizeof ( *pCurMsg ) ) {
|
||||
return ECA_TOLARGE;
|
||||
}
|
||||
|
||||
pCurMsg = reinterpret_cast <caHdr *> (pInBuf);
|
||||
pCurMsg = reinterpret_cast <caHdr *> ( pInBuf );
|
||||
|
||||
/*
|
||||
* fix endian of bytes
|
||||
*/
|
||||
pCurMsg->m_postsize = ntohs (pCurMsg->m_postsize);
|
||||
pCurMsg->m_cmmd = ntohs (pCurMsg->m_cmmd);
|
||||
pCurMsg->m_dataType = ntohs (pCurMsg->m_dataType);
|
||||
pCurMsg->m_count = ntohs (pCurMsg->m_count);
|
||||
pCurMsg->m_postsize = ntohs ( pCurMsg->m_postsize );
|
||||
pCurMsg->m_cmmd = ntohs ( pCurMsg->m_cmmd );
|
||||
pCurMsg->m_dataType = ntohs ( pCurMsg->m_dataType );
|
||||
pCurMsg->m_count = ntohs ( pCurMsg->m_count );
|
||||
|
||||
#if 0
|
||||
printf ("UDP Cmd=%3d Type=%3d Count=%4d Size=%4d",
|
||||
printf ( "UDP Cmd=%3d Type=%3d Count=%4d Size=%4d",
|
||||
pCurMsg->m_cmmd,
|
||||
pCurMsg->m_dataType,
|
||||
pCurMsg->m_count,
|
||||
pCurMsg->m_postsize);
|
||||
pCurMsg->m_postsize );
|
||||
printf (" Avail=%8x Cid=%6d\n",
|
||||
pCurMsg->m_available,
|
||||
pCurMsg->m_cid);
|
||||
pCurMsg->m_cid );
|
||||
#endif
|
||||
|
||||
size = pCurMsg->m_postsize + sizeof (*pCurMsg);
|
||||
size = pCurMsg->m_postsize + sizeof ( *pCurMsg );
|
||||
|
||||
/*
|
||||
* dont allow msg body extending beyond frame boundary
|
||||
@@ -762,13 +687,13 @@ int udpiiu::post_msg (const struct sockaddr_in *pnet_addr,
|
||||
* execute the response message
|
||||
*/
|
||||
pProtoStubUDP pStub;
|
||||
if ( pCurMsg->m_cmmd>=NELEMENTS (udpJumpTableCAC) ) {
|
||||
pStub = bad_udp_resp_action;
|
||||
if ( pCurMsg->m_cmmd >= NELEMENTS ( udpJumpTableCAC ) ) {
|
||||
pStub = badUDPRespAction;
|
||||
}
|
||||
else {
|
||||
pStub = udpJumpTableCAC [pCurMsg->m_cmmd];
|
||||
}
|
||||
(*pStub) (this, pCurMsg, pnet_addr);
|
||||
(this->*pStub) ( *pCurMsg, net_addr);
|
||||
|
||||
blockSize -= size;
|
||||
pInBuf += size;;
|
||||
@@ -789,110 +714,44 @@ const char * udpiiu::pHostName () const
|
||||
return "<disconnected>";
|
||||
}
|
||||
|
||||
bool udpiiu::ca_v42_ok () const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool udpiiu::ca_v41_ok () const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool udpiiu::compareIfTCP (nciu &, const sockaddr_in &) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add chan to iiu and guarantee that
|
||||
* one chan on the B cast iiu list is pointed to by
|
||||
* ca_pEndOfBCastList
|
||||
*/
|
||||
void udpiiu::addToChanList ( nciu &chan )
|
||||
{
|
||||
this->pcas->lock ();
|
||||
|
||||
/*
|
||||
* add to the beginning of the list so that search requests for
|
||||
* this channel will be sent first (since the retry count is zero)
|
||||
*/
|
||||
if ( ellCount ( &this->chidList ) == 0 ) {
|
||||
this->pcas->endOfBCastList = tsDLIterBD <nciu> ( &chan );
|
||||
}
|
||||
/*
|
||||
* add to the front of the list so that
|
||||
* search requests for new channels will be sent first
|
||||
*/
|
||||
chan.retry = 0u;
|
||||
this->chidList.push ( chan );
|
||||
chan.piiu = this;
|
||||
|
||||
this->pcas->unlock ();
|
||||
}
|
||||
|
||||
void udpiiu::removeFromChanList ( nciu &chan )
|
||||
{
|
||||
tsDLIterBD <nciu> iter ( &chan );
|
||||
|
||||
this->pcas->lock ();
|
||||
if ( chan.piiu->pcas->endOfBCastList == iter ) {
|
||||
if ( iter.itemBefore ().valid () ) {
|
||||
chan.piiu->pcas->endOfBCastList = iter.itemBefore ();
|
||||
}
|
||||
else {
|
||||
chan.piiu->pcas->endOfBCastList =
|
||||
tsDLIterBD<nciu> ( chan.piiu->chidList.last () );
|
||||
}
|
||||
}
|
||||
chan.piiu->chidList.remove ( chan );
|
||||
chan.piiu = NULL;
|
||||
this->pcas->unlock ();
|
||||
}
|
||||
|
||||
void udpiiu::disconnect ( nciu & /* chan */ )
|
||||
{
|
||||
// NOOP
|
||||
}
|
||||
|
||||
/*
|
||||
* udpiiu::pushDatagramMsg ()
|
||||
*/
|
||||
int udpiiu::pushDatagramMsg (const caHdr *pMsg, const void *pExt, ca_uint16_t extsize)
|
||||
bool udpiiu::pushDatagramMsg ( const caHdr &msg, const void *pExt, ca_uint16_t extsize )
|
||||
{
|
||||
unsigned long msgsize;
|
||||
ca_uint16_t allignedExtSize;
|
||||
caHdr *pbufmsg;
|
||||
|
||||
allignedExtSize = CA_MESSAGE_ALIGN (extsize);
|
||||
msgsize = sizeof (caHdr) + allignedExtSize;
|
||||
allignedExtSize = CA_MESSAGE_ALIGN ( extsize );
|
||||
msgsize = sizeof ( caHdr ) + allignedExtSize;
|
||||
|
||||
|
||||
/* fail out if max message size exceeded */
|
||||
if ( msgsize >= sizeof (this->xmitBuf)-7 ) {
|
||||
return ECA_TOLARGE;
|
||||
if ( msgsize >= sizeof ( this->xmitBuf ) - 7 ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
semMutexMustTake (this->xmitBufLock);
|
||||
this->lock ();
|
||||
|
||||
if ( msgsize + this->nBytesInXmitBuf > sizeof ( this->xmitBuf ) ) {
|
||||
semMutexGive (this->xmitBufLock);
|
||||
return ECA_TOLARGE;
|
||||
this->unlock ();
|
||||
return false;
|
||||
}
|
||||
|
||||
pbufmsg = (caHdr *) &this->xmitBuf[this->nBytesInXmitBuf];
|
||||
*pbufmsg = *pMsg;
|
||||
memcpy (pbufmsg+1, pExt, extsize);
|
||||
*pbufmsg = msg;
|
||||
memcpy ( pbufmsg+1, pExt, extsize );
|
||||
if ( extsize != allignedExtSize ) {
|
||||
char *pDest = (char *) (pbufmsg+1);
|
||||
memset (pDest + extsize, '\0', allignedExtSize - extsize);
|
||||
char *pDest = (char *) ( pbufmsg + 1 );
|
||||
memset ( pDest + extsize, '\0', allignedExtSize - extsize );
|
||||
}
|
||||
pbufmsg->m_postsize = htons (allignedExtSize);
|
||||
pbufmsg->m_postsize = htons ( allignedExtSize );
|
||||
this->nBytesInXmitBuf += msgsize;
|
||||
|
||||
semMutexGive (this->xmitBufLock);
|
||||
this->unlock ();
|
||||
|
||||
return ECA_NORMAL;
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
@@ -902,7 +761,12 @@ void udpiiu::flush ()
|
||||
{
|
||||
osiSockAddrNode *pNode;
|
||||
|
||||
semMutexMustTake (this->xmitBufLock);
|
||||
this->lock ();
|
||||
|
||||
if ( this->nBytesInXmitBuf == 0u ) {
|
||||
this->unlock ();
|
||||
return;
|
||||
}
|
||||
|
||||
pNode = (osiSockAddrNode *) ellFirst ( &this->dest );
|
||||
while ( pNode ) {
|
||||
@@ -940,7 +804,7 @@ void udpiiu::flush ()
|
||||
else {
|
||||
char buf[64];
|
||||
|
||||
ipAddrToA ( &pNode->addr.ia, buf, sizeof ( buf ) );
|
||||
sockAddrToA ( &pNode->addr.sa, buf, sizeof ( buf ) );
|
||||
|
||||
ca_printf (
|
||||
"CAC: error = \"%s\" sending UDP msg to %s\n",
|
||||
@@ -954,17 +818,12 @@ void udpiiu::flush ()
|
||||
|
||||
this->nBytesInXmitBuf = 0u;
|
||||
|
||||
semMutexGive ( this->xmitBufLock );
|
||||
}
|
||||
|
||||
int udpiiu::pushStreamMsg ( const caHdr * /* pmsg */,
|
||||
const void * /* pext */, bool /* blockingOk */ )
|
||||
{
|
||||
ca_printf ("in pushStreamMsg () for a udp iiu?\n");
|
||||
return ECA_DISCONNCHID;
|
||||
this->unlock ();
|
||||
}
|
||||
|
||||
SOCKET udpiiu::getSock () const
|
||||
{
|
||||
return this->sock;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user