large array changes
This commit is contained in:
+5
-5
@@ -153,7 +153,7 @@ bool CASG::ioComplete () const
|
||||
return ( this->ioList.count () == 0u );
|
||||
}
|
||||
|
||||
int CASG::put ( chid pChan, unsigned type, unsigned long count, const void *pValue )
|
||||
int CASG::put ( chid pChan, unsigned type, arrayElementCount count, const void *pValue )
|
||||
{
|
||||
try {
|
||||
epicsAutoMutex locker ( this->mutex );
|
||||
@@ -191,7 +191,7 @@ int CASG::put ( chid pChan, unsigned type, unsigned long count, const void *pVal
|
||||
{
|
||||
return ECA_NOTINSERVICE;
|
||||
}
|
||||
catch ( cacChannel::noMemory & )
|
||||
catch ( std::bad_alloc & )
|
||||
{
|
||||
return ECA_ALLOCMEM;
|
||||
}
|
||||
@@ -201,7 +201,7 @@ int CASG::put ( chid pChan, unsigned type, unsigned long count, const void *pVal
|
||||
}
|
||||
}
|
||||
|
||||
int CASG::get ( chid pChan, unsigned type, unsigned long count, void *pValue )
|
||||
int CASG::get ( chid pChan, unsigned type, arrayElementCount count, void *pValue )
|
||||
{
|
||||
|
||||
try {
|
||||
@@ -240,7 +240,7 @@ int CASG::get ( chid pChan, unsigned type, unsigned long count, void *pValue )
|
||||
{
|
||||
return ECA_NOTINSERVICE;
|
||||
}
|
||||
catch ( cacChannel::noMemory & )
|
||||
catch ( std::bad_alloc & )
|
||||
{
|
||||
return ECA_ALLOCMEM;
|
||||
}
|
||||
@@ -300,4 +300,4 @@ int CASG::printf ( const char *pformat, ... )
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
+35
-96
@@ -12,6 +12,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <new>
|
||||
|
||||
#define epicsAssertAuthor "Jeff Hill johill@lanl.gov"
|
||||
|
||||
|
||||
@@ -81,32 +83,6 @@ int fetchClientContext ( oldCAC **ppcac )
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
* Default Exception Handler
|
||||
*/
|
||||
extern "C" void ca_default_exception_handler ( struct exception_handler_args args )
|
||||
{
|
||||
if ( args.chid && args.op != CA_OP_OTHER ) {
|
||||
ca_signal_formated (
|
||||
args.stat,
|
||||
args.pFile,
|
||||
args.lineNo,
|
||||
"%s - with request chan=%s op=%ld data type=%s count=%ld",
|
||||
args.ctx,
|
||||
ca_name ( args.chid ),
|
||||
args.op,
|
||||
dbr_type_to_text ( args.type ),
|
||||
args.count );
|
||||
}
|
||||
else {
|
||||
ca_signal_formated (
|
||||
args.stat,
|
||||
args.pFile,
|
||||
args.lineNo,
|
||||
args.ctx );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* ca_task_initialize ()
|
||||
*/
|
||||
@@ -211,7 +187,7 @@ extern "C" int epicsShareAPI ca_task_exit ()
|
||||
* backwards compatible entry point to ca_search_and_connect()
|
||||
*/
|
||||
extern "C" int epicsShareAPI ca_build_and_connect ( const char *name_str, chtype get_type,
|
||||
unsigned long get_count, chid * chan, void *pvalue,
|
||||
arrayElementCount get_count, chid * chan, void *pvalue,
|
||||
caCh *conn_func, void *puser )
|
||||
{
|
||||
if ( get_type != TYPENOTCONN && pvalue != 0 && get_count != 0 ) {
|
||||
@@ -269,7 +245,7 @@ extern "C" int epicsShareAPI ca_clear_channel ( chid pChan )
|
||||
* ca_array_get ()
|
||||
*/
|
||||
extern "C" int epicsShareAPI ca_array_get ( chtype type,
|
||||
unsigned long count, chid pChan, void *pValue )
|
||||
arrayElementCount count, chid pChan, void *pValue )
|
||||
{
|
||||
oldCAC *pcac;
|
||||
int caStatus = fetchClientContext ( &pcac );
|
||||
@@ -283,7 +259,7 @@ extern "C" int epicsShareAPI ca_array_get ( chtype type,
|
||||
unsigned tmpType = static_cast < unsigned > ( type );
|
||||
|
||||
autoPtrDestroy < getCopy > pNotify
|
||||
( new getCopy ( *pcac, tmpType, count, pValue ) );
|
||||
( new getCopy ( *pcac, *pChan, tmpType, count, pValue ) );
|
||||
if ( ! pNotify.get() ) {
|
||||
return ECA_ALLOCMEM;
|
||||
}
|
||||
@@ -317,10 +293,13 @@ extern "C" int epicsShareAPI ca_array_get ( chtype type,
|
||||
{
|
||||
return ECA_NOTINSERVICE;
|
||||
}
|
||||
catch ( cacChannel::noMemory & )
|
||||
catch ( std::bad_alloc & )
|
||||
{
|
||||
return ECA_ALLOCMEM;
|
||||
}
|
||||
catch ( cacChannel::msgBodyCacheTooSmall ) {
|
||||
return ECA_TOLARGE;
|
||||
}
|
||||
catch ( ... )
|
||||
{
|
||||
return ECA_GETFAIL;
|
||||
@@ -331,7 +310,7 @@ extern "C" int epicsShareAPI ca_array_get ( chtype type,
|
||||
* ca_array_get_callback ()
|
||||
*/
|
||||
extern "C" int epicsShareAPI ca_array_get_callback ( chtype type,
|
||||
unsigned long count, chid pChan,
|
||||
arrayElementCount count, chid pChan,
|
||||
caEventCallBackFunc *pfunc, void *arg )
|
||||
{
|
||||
if ( type < 0 ) {
|
||||
@@ -374,10 +353,13 @@ extern "C" int epicsShareAPI ca_array_get_callback ( chtype type,
|
||||
{
|
||||
return ECA_NOTINSERVICE;
|
||||
}
|
||||
catch ( cacChannel::noMemory & )
|
||||
catch ( std::bad_alloc & )
|
||||
{
|
||||
return ECA_ALLOCMEM;
|
||||
}
|
||||
catch ( cacChannel::msgBodyCacheTooSmall ) {
|
||||
return ECA_TOLARGE;
|
||||
}
|
||||
catch ( ... )
|
||||
{
|
||||
return ECA_GETFAIL;
|
||||
@@ -387,7 +369,7 @@ extern "C" int epicsShareAPI ca_array_get_callback ( chtype type,
|
||||
/*
|
||||
* ca_array_put_callback ()
|
||||
*/
|
||||
extern "C" int epicsShareAPI ca_array_put_callback ( chtype type, unsigned long count,
|
||||
extern "C" int epicsShareAPI ca_array_put_callback ( chtype type, arrayElementCount count,
|
||||
chid pChan, const void *pValue, caEventCallBackFunc *pfunc, void *usrarg )
|
||||
{
|
||||
if ( type < 0 ) {
|
||||
@@ -430,7 +412,7 @@ extern "C" int epicsShareAPI ca_array_put_callback ( chtype type, unsigned long
|
||||
{
|
||||
return ECA_NOTINSERVICE;
|
||||
}
|
||||
catch ( cacChannel::noMemory & )
|
||||
catch ( std::bad_alloc & )
|
||||
{
|
||||
return ECA_ALLOCMEM;
|
||||
}
|
||||
@@ -443,7 +425,7 @@ extern "C" int epicsShareAPI ca_array_put_callback ( chtype type, unsigned long
|
||||
/*
|
||||
* ca_array_put ()
|
||||
*/
|
||||
extern "C" int epicsShareAPI ca_array_put ( chtype type, unsigned long count,
|
||||
extern "C" int epicsShareAPI ca_array_put ( chtype type, arrayElementCount count,
|
||||
chid pChan, const void *pValue )
|
||||
{
|
||||
if ( type < 0 ) {
|
||||
@@ -479,7 +461,7 @@ extern "C" int epicsShareAPI ca_array_put ( chtype type, unsigned long count,
|
||||
{
|
||||
return ECA_NOTINSERVICE;
|
||||
}
|
||||
catch ( cacChannel::noMemory & )
|
||||
catch ( std::bad_alloc & )
|
||||
{
|
||||
return ECA_ALLOCMEM;
|
||||
}
|
||||
@@ -526,7 +508,7 @@ extern "C" int epicsShareAPI ca_add_exception_event ( caExceptionHandler *pfunc,
|
||||
* ca_add_masked_array_event
|
||||
*/
|
||||
extern "C" int epicsShareAPI ca_add_masked_array_event (
|
||||
chtype type, unsigned long count, chid pChan,
|
||||
chtype type, arrayElementCount count, chid pChan,
|
||||
caEventCallBackFunc *pCallBack, void *pCallBackArg,
|
||||
ca_real, ca_real, ca_real,
|
||||
evid *monixptr, long mask )
|
||||
@@ -553,20 +535,6 @@ extern "C" int epicsShareAPI ca_add_masked_array_event (
|
||||
return ECA_BADMASK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check for huge waveform
|
||||
*
|
||||
* (the count is not checked here against the native count
|
||||
* when connected because this introduces a race condition
|
||||
* for the client tool - the requested count is clipped to
|
||||
* the actual count when the monitor request is sent so
|
||||
* verifying that the requested count is valid here isnt
|
||||
* required)
|
||||
*/
|
||||
if ( dbr_size_n ( type, count ) > MAX_MSG_SIZE - sizeof ( caHdr ) ) {
|
||||
return ECA_TOLARGE;
|
||||
}
|
||||
|
||||
try {
|
||||
autoPtrDestroy < oldSubscription > pSubsr
|
||||
( new oldSubscription (
|
||||
@@ -600,10 +568,13 @@ extern "C" int epicsShareAPI ca_add_masked_array_event (
|
||||
{
|
||||
return ECA_NOTINSERVICE;
|
||||
}
|
||||
catch ( cacChannel::noMemory & )
|
||||
catch ( std::bad_alloc & )
|
||||
{
|
||||
return ECA_ALLOCMEM;
|
||||
}
|
||||
catch ( cacChannel::msgBodyCacheTooSmall ) {
|
||||
return ECA_TOLARGE;
|
||||
}
|
||||
catch ( ... )
|
||||
{
|
||||
return ECA_INTERNAL;
|
||||
@@ -732,56 +703,24 @@ extern "C" void epicsShareAPI ca_signal_formated ( long ca_status, const char *p
|
||||
int lineno, const char *pFormat, ... )
|
||||
{
|
||||
oldCAC *pcac;
|
||||
va_list theArgs;
|
||||
static const char *severity[] =
|
||||
{
|
||||
"Warning",
|
||||
"Success",
|
||||
"Error",
|
||||
"Info",
|
||||
"Fatal",
|
||||
"Fatal",
|
||||
"Fatal",
|
||||
"Fatal"
|
||||
};
|
||||
|
||||
if ( caClientContextId ) {
|
||||
pcac = (oldCAC *) epicsThreadPrivateGet ( caClientContextId );
|
||||
pcac = ( oldCAC * ) epicsThreadPrivateGet ( caClientContextId );
|
||||
}
|
||||
else {
|
||||
pcac = NULL;
|
||||
pcac = 0;
|
||||
}
|
||||
|
||||
va_start ( theArgs, pFormat );
|
||||
|
||||
pcac->printf ( "CA.Client.Diagnostic..............................................\n" );
|
||||
|
||||
pcac->printf ( " %s: \"%s\"\n",
|
||||
severity[ CA_EXTRACT_SEVERITY ( ca_status ) ],
|
||||
ca_message ( ca_status ) );
|
||||
|
||||
if ( pFormat ) {
|
||||
pcac->printf ( " Context: \"" );
|
||||
pcac->vPrintf ( pFormat, theArgs );
|
||||
pcac->printf ( "\"\n" );
|
||||
va_list theArgs;
|
||||
va_start ( theArgs, pFormat );
|
||||
if ( pcac ) {
|
||||
pcac->vSignal ( ca_status, pfilenm, lineno, pFormat, theArgs );
|
||||
}
|
||||
|
||||
if (pfilenm) {
|
||||
pcac->printf ( " Source File: %s Line Number: %d\n",
|
||||
pfilenm, lineno );
|
||||
else {
|
||||
fprintf ( stderr, "file=%s line=%d: CA exception delivered to a thread w/o ca context\n",
|
||||
pfilenm, lineno );
|
||||
vfprintf ( stderr, pFormat, theArgs );
|
||||
}
|
||||
|
||||
/*
|
||||
* Terminate execution if unsuccessful
|
||||
*/
|
||||
if( ! ( ca_status & CA_M_SUCCESS ) &&
|
||||
CA_EXTRACT_SEVERITY ( ca_status ) != CA_K_WARNING ){
|
||||
errlogFlush();
|
||||
abort();
|
||||
}
|
||||
|
||||
pcac->printf ( "..................................................................\n" );
|
||||
|
||||
va_end ( theArgs );
|
||||
}
|
||||
|
||||
@@ -836,7 +775,7 @@ extern "C" int epicsShareAPI ca_v42_ok ( chid pChan )
|
||||
*/
|
||||
extern "C" const char * epicsShareAPI ca_version ()
|
||||
{
|
||||
return CA_VERSION_STRING;
|
||||
return CA_VERSION_STRING ( CA_MINOR_PROTOCOL_REVISION );
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -866,7 +805,7 @@ extern "C" short epicsShareAPI ca_field_type ( chid pChan )
|
||||
/*
|
||||
* ca_element_count ()
|
||||
*/
|
||||
extern "C" unsigned long epicsShareAPI ca_element_count ( chid pChan )
|
||||
extern "C" arrayElementCount epicsShareAPI ca_element_count ( chid pChan )
|
||||
{
|
||||
return pChan->nativeElementCount ();
|
||||
}
|
||||
|
||||
+66
-15
@@ -617,7 +617,7 @@ void performCtrlDoubleTest (chid chan)
|
||||
ca_element_count(chan),
|
||||
chan, pCtrlDbl);
|
||||
SEVCHK (status, "performCtrlDoubleTest, ca_array_get");
|
||||
status = ca_pend_io (20.0);
|
||||
status = ca_pend_io (30.0);
|
||||
assert (status==ECA_NORMAL);
|
||||
|
||||
/*
|
||||
@@ -1246,17 +1246,37 @@ void eventClearTest ( chid chan )
|
||||
SEVCHK ( status, NULL);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* array test
|
||||
*
|
||||
* verify that we can at least write and read back the same array
|
||||
* if multiple elements are present
|
||||
*/
|
||||
static arrayReadNotifyComplete = 0;
|
||||
static arrayWriteNotifyComplete = 0;
|
||||
void arrayReadNotify ( struct event_handler_args args )
|
||||
{
|
||||
dbr_double_t *pWF = ( dbr_double_t * ) ( args.usr );
|
||||
dbr_double_t *pRF = ( dbr_double_t * ) ( args.dbr );
|
||||
int i;
|
||||
for ( i = 0; i < args.count; i++ ) {
|
||||
if ( pWF[i] != pRF[i] ) {
|
||||
assert ( 0 );
|
||||
}
|
||||
}
|
||||
arrayReadNotifyComplete = 1;
|
||||
}
|
||||
void arrayWriteNotify ( struct event_handler_args args )
|
||||
{
|
||||
arrayWriteNotifyComplete = 1;
|
||||
}
|
||||
void arrayTest ( chid chan )
|
||||
{
|
||||
dbr_double_t *pRF, *pWF;
|
||||
unsigned i;
|
||||
int status;
|
||||
evid id;
|
||||
|
||||
if ( ! ca_write_access ( chan ) ) {
|
||||
printf ( "skipping array test - no write access\n" );
|
||||
@@ -1293,7 +1313,7 @@ void arrayTest ( chid chan )
|
||||
/*
|
||||
* verify read response matches values written
|
||||
*/
|
||||
for ( i = 0; i < ca_element_count (chan); i++ ) {
|
||||
for ( i = 0; i < ca_element_count ( chan ); i++ ) {
|
||||
assert ( pWF[i] == pRF[i] );
|
||||
}
|
||||
|
||||
@@ -1302,26 +1322,55 @@ void arrayTest ( chid chan )
|
||||
*/
|
||||
{
|
||||
char *pRS;
|
||||
/* clip to 16k message buffer limit */
|
||||
unsigned maxElem = ( ( 1 << 14 ) - 16 ) / MAX_STRING_SIZE;
|
||||
unsigned nElem;
|
||||
|
||||
if ( maxElem > ca_element_count (chan) ) {
|
||||
nElem = ca_element_count (chan);
|
||||
}
|
||||
else {
|
||||
nElem = maxElem;
|
||||
}
|
||||
|
||||
pRS = malloc ( nElem * MAX_STRING_SIZE );
|
||||
pRS = malloc ( ca_element_count (chan) * MAX_STRING_SIZE );
|
||||
assert ( pRS );
|
||||
status = ca_array_get ( DBR_STRING, nElem, chan, pRS );
|
||||
status = ca_array_get ( DBR_STRING,
|
||||
ca_element_count (chan), chan, pRS );
|
||||
SEVCHK ( status, "array read request failed" );
|
||||
status = ca_pend_io ( 30.0 );
|
||||
SEVCHK ( status, "array read failed" );
|
||||
free ( pRS );
|
||||
}
|
||||
|
||||
/*
|
||||
* write some random numbers into the array
|
||||
*/
|
||||
for ( i = 0; i < ca_element_count (chan); i++ ) {
|
||||
pWF[i] = rand ();
|
||||
pRF[i] = - pWF[i];
|
||||
}
|
||||
status = ca_array_put_callback ( DBR_DOUBLE, ca_element_count ( chan ),
|
||||
chan, pWF, arrayWriteNotify, 0 );
|
||||
SEVCHK ( status, "array write notify request failed" );
|
||||
status = ca_array_get_callback ( DBR_DOUBLE, ca_element_count (chan),
|
||||
chan, arrayReadNotify, pWF );
|
||||
SEVCHK ( status, "array read notify request failed" );
|
||||
|
||||
while ( ! arrayWriteNotifyComplete && ! arrayReadNotifyComplete ) {
|
||||
ca_pend_event ( 0.1 );
|
||||
}
|
||||
|
||||
/*
|
||||
* write some random numbers into the array
|
||||
*/
|
||||
for ( i = 0; i < ca_element_count (chan); i++ ) {
|
||||
pWF[i] = rand ();
|
||||
pRF[i] = - pWF[i];
|
||||
}
|
||||
arrayReadNotifyComplete = 0;
|
||||
status = ca_array_put ( DBR_DOUBLE, ca_element_count ( chan ),
|
||||
chan, pWF );
|
||||
SEVCHK ( status, "array write notify request failed" );
|
||||
status = ca_add_array_event ( DBR_DOUBLE, ca_element_count ( chan ),
|
||||
chan, arrayReadNotify, pWF, 0.0, 0.0, 0.0, &id );
|
||||
SEVCHK ( status, "array subscription request failed" );
|
||||
while ( ! arrayReadNotifyComplete ) {
|
||||
ca_pend_event ( 0.1 );
|
||||
}
|
||||
status = ca_clear_event ( id );
|
||||
SEVCHK ( status, "clear event request failed" );
|
||||
|
||||
free ( pRF );
|
||||
free ( pWF );
|
||||
|
||||
@@ -1629,6 +1678,8 @@ int acctst ( char *pName, unsigned channelCount, unsigned repetitionCount )
|
||||
|
||||
printf ( "CA Client V%s, channel name \"%s\"\n", ca_version (), pName );
|
||||
|
||||
putenv ( "EPICS_CA_MAX_ARRAY_BYTES=10000000" );
|
||||
|
||||
verifyDataTypeMacros ();
|
||||
|
||||
connections = ca_get_ioc_connection_count ();
|
||||
@@ -1646,6 +1697,7 @@ int acctst ( char *pName, unsigned channelCount, unsigned repetitionCount )
|
||||
printf ( "testing with a local channel\n" );
|
||||
}
|
||||
|
||||
arrayTest ( chan );
|
||||
verifyMonitorSubscriptionFlushIO ( chan );
|
||||
monitorSubscriptionFirstUpdateTest ( chan );
|
||||
performGrEnumTest ( chan );
|
||||
@@ -1665,7 +1717,6 @@ int acctst ( char *pName, unsigned channelCount, unsigned repetitionCount )
|
||||
test_sync_groups ( chan );
|
||||
performDeleteTest ( chan );
|
||||
eventClearTest ( chan );
|
||||
arrayTest ( chan );
|
||||
performMonitorUpdateTest ( chan );
|
||||
|
||||
/*
|
||||
|
||||
+5
-5
@@ -43,11 +43,11 @@ bhe::~bhe ()
|
||||
*
|
||||
* updates beacon period, and looks for beacon anomalies
|
||||
*/
|
||||
bool bhe::updatePeriod ( epicsTime programBeginTime )
|
||||
bool bhe::updatePeriod ( const epicsTime & programBeginTime,
|
||||
const epicsTime & currentTime )
|
||||
{
|
||||
double currentPeriod;
|
||||
bool netChange = false;
|
||||
epicsTime current = epicsTime::getCurrent ();
|
||||
|
||||
if ( this->timeStamp == epicsTime () ) {
|
||||
|
||||
@@ -61,7 +61,7 @@ bool bhe::updatePeriod ( epicsTime programBeginTime )
|
||||
* a TCP/IP connection created the beacon.
|
||||
* (nothing to do but set the beacon time stamp and return)
|
||||
*/
|
||||
this->timeStamp = current;
|
||||
this->timeStamp = currentTime;
|
||||
|
||||
return netChange;
|
||||
}
|
||||
@@ -69,7 +69,7 @@ bool bhe::updatePeriod ( epicsTime programBeginTime )
|
||||
/*
|
||||
* compute the beacon period (if we have seen at least two beacons)
|
||||
*/
|
||||
currentPeriod = current - this->timeStamp;
|
||||
currentPeriod = currentTime - this->timeStamp;
|
||||
if ( this->averagePeriod < 0.0 ) {
|
||||
double totalRunningTime;
|
||||
|
||||
@@ -158,7 +158,7 @@ bool bhe::updatePeriod ( epicsTime programBeginTime )
|
||||
this->averagePeriod = currentPeriod * 0.125 + this->averagePeriod * 0.875;
|
||||
}
|
||||
|
||||
this->timeStamp = current;
|
||||
this->timeStamp = currentTime;
|
||||
|
||||
return netChange;
|
||||
}
|
||||
|
||||
+14
-4
@@ -40,8 +40,10 @@ public:
|
||||
epicsShareFunc bhe ( const epicsTime &initialTimeStamp, const inetAddrID &addr );
|
||||
tcpiiu *getIIU () const;
|
||||
void bindToIIU ( tcpiiu & );
|
||||
void unbindFromIIU ();
|
||||
epicsShareFunc void destroy ();
|
||||
epicsShareFunc bool updatePeriod ( epicsTime programBeginTime );
|
||||
epicsShareFunc bool updatePeriod ( const epicsTime &programBeginTime,
|
||||
const epicsTime & currentTime );
|
||||
epicsShareFunc double period () const;
|
||||
epicsShareFunc void show ( unsigned level) const;
|
||||
epicsShareFunc void * operator new ( size_t size );
|
||||
@@ -71,13 +73,14 @@ private:
|
||||
* between the 1st and 2nd beacons)
|
||||
*/
|
||||
inline bhe::bhe ( const epicsTime &initialTimeStamp, const inetAddrID &addr ) :
|
||||
inetAddrID (addr), piiu (0), timeStamp (initialTimeStamp), averagePeriod ( - DBL_MAX )
|
||||
inetAddrID ( addr ), piiu ( 0 ),
|
||||
timeStamp ( initialTimeStamp ), averagePeriod ( - DBL_MAX )
|
||||
{
|
||||
# ifdef DEBUG
|
||||
{
|
||||
char name[64];
|
||||
ipAddrToDottedIP (&addr, name, sizeof(name));
|
||||
::printf ("created beacon entry for %s\n", name);
|
||||
addr.name ( name, sizeof ( name ) );
|
||||
::printf ( "created beacon entry for %s\n", name );
|
||||
}
|
||||
# endif
|
||||
}
|
||||
@@ -95,6 +98,13 @@ inline void bhe::bindToIIU ( tcpiiu &iiuIn )
|
||||
}
|
||||
}
|
||||
|
||||
inline void bhe::unbindFromIIU ()
|
||||
{
|
||||
this->piiu = 0;
|
||||
this->timeStamp = epicsTime();
|
||||
this->averagePeriod = - DBL_MAX;
|
||||
}
|
||||
|
||||
#endif // ifdef bheh
|
||||
|
||||
|
||||
|
||||
+43
-47
@@ -35,55 +35,57 @@
|
||||
#define capStrOfX(A) capStrOf ( A )
|
||||
|
||||
/*
|
||||
* CA protocol number
|
||||
* CA protocol revision
|
||||
* TCP/UDP port number (bumped each major protocol change)
|
||||
*/
|
||||
#define CA_PROTOCOL_VERSION 4
|
||||
#define CA_MINOR_VERSION 8
|
||||
#define CA_VERSION_STRING \
|
||||
( capStrOfX ( CA_PROTOCOL_VERSION ) "." capStrOfX ( CA_MINOR_VERSION ) )
|
||||
#define CA_MAJOR_PROTOCOL_REVISION 4
|
||||
#define CA_VERSION_STRING( MINOR_REVISION ) \
|
||||
( capStrOfX ( CA_MAJOR_PROTOCOL_REVISION ) "." capStrOfX ( MINOR_REVISION ) )
|
||||
#define CA_UKN_MINOR_VERSION 0u /* unknown minor version */
|
||||
#if CA_PROTOCOL_VERSION == 4u
|
||||
# define CA_V41(MAJOR,MINOR) ((MINOR)>=1u)
|
||||
# define CA_V42(MAJOR,MINOR) ((MINOR)>=2u)
|
||||
# define CA_V43(MAJOR,MINOR) ((MINOR)>=3u)
|
||||
# define CA_V44(MAJOR,MINOR) ((MINOR)>=4u)
|
||||
# define CA_V45(MAJOR,MINOR) ((MINOR)>=5u)
|
||||
# define CA_V46(MAJOR,MINOR) ((MINOR)>=6u)
|
||||
# define CA_V47(MAJOR,MINOR) ((MINOR)>=7u)
|
||||
# define CA_V48(MAJOR,MINOR) ((MINOR)>=8u)
|
||||
#elif CA_PROTOCOL_VERSION > 4u
|
||||
# define CA_V41(MAJOR,MINOR) ( 1u )
|
||||
# define CA_V42(MAJOR,MINOR) ( 1u )
|
||||
# define CA_V43(MAJOR,MINOR) ( 1u )
|
||||
# define CA_V44(MAJOR,MINOR) ( 1u )
|
||||
# define CA_V45(MAJOR,MINOR) ( 1u )
|
||||
# define CA_V46(MAJOR,MINOR) ( 1u )
|
||||
# define CA_V47(MAJOR,MINOR) ( 1u )
|
||||
# define CA_V48(MAJOR,MINOR) ( 1u )
|
||||
#if CA_MAJOR_PROTOCOL_REVISION == 4u
|
||||
# define CA_V41(MINOR) ((MINOR)>=1u)
|
||||
# define CA_V42(MINOR) ((MINOR)>=2u)
|
||||
# define CA_V43(MINOR) ((MINOR)>=3u)
|
||||
# define CA_V44(MINOR) ((MINOR)>=4u)
|
||||
# define CA_V45(MINOR) ((MINOR)>=5u)
|
||||
# define CA_V46(MINOR) ((MINOR)>=6u)
|
||||
# define CA_V47(MINOR) ((MINOR)>=7u)
|
||||
# define CA_V48(MINOR) ((MINOR)>=8u)
|
||||
# define CA_V49(MINOR) ((MINOR)>=9u)
|
||||
#elif CA_MAJOR_PROTOCOL_REVISION > 4u
|
||||
# define CA_V41(MINOR) ( 1u )
|
||||
# define CA_V42(MINOR) ( 1u )
|
||||
# define CA_V43(MINOR) ( 1u )
|
||||
# define CA_V44(MINOR) ( 1u )
|
||||
# define CA_V45(MINOR) ( 1u )
|
||||
# define CA_V46(MINOR) ( 1u )
|
||||
# define CA_V47(MINOR) ( 1u )
|
||||
# define CA_V48(MINOR) ( 1u )
|
||||
# define CA_V49(MINOR) ( 1u )
|
||||
#else
|
||||
# define CA_V41(MAJOR,MINOR) ( 0u )
|
||||
# define CA_V42(MAJOR,MINOR) ( 0u )
|
||||
# define CA_V43(MAJOR,MINOR) ( 0u )
|
||||
# define CA_V44(MAJOR,MINOR) ( 0u )
|
||||
# define CA_V45(MAJOR,MINOR) ( 0u )
|
||||
# define CA_V46(MAJOR,MINOR) ( 0u )
|
||||
# define CA_V47(MAJOR,MINOR) ( 0u )
|
||||
# define CA_V48(MAJOR,MINOR) ( 0u )
|
||||
# define CA_V41(MINOR) ( 0u )
|
||||
# define CA_V42(MINOR) ( 0u )
|
||||
# define CA_V43(MINOR) ( 0u )
|
||||
# define CA_V44(MINOR) ( 0u )
|
||||
# define CA_V45(MINOR) ( 0u )
|
||||
# define CA_V46(MINOR) ( 0u )
|
||||
# define CA_V47(MINOR) ( 0u )
|
||||
# define CA_V48(MINOR) ( 0u )
|
||||
# define CA_V49(MINOR) ( 0u )
|
||||
#endif
|
||||
|
||||
/*
|
||||
* NOTE: These port numbers are only used if the CA repeater and
|
||||
* These port numbers are only used if the CA repeater and
|
||||
* CA server port numbers cant be obtained from the EPICS
|
||||
* 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)
|
||||
#define CA_SERVER_PORT (CA_PORT_BASE+CA_MAJOR_PROTOCOL_REVISION*2u)
|
||||
#define CA_REPEATER_PORT (CA_PORT_BASE+CA_MAJOR_PROTOCOL_REVISION*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)
|
||||
* (the MTU of Ethernet is currently independent of its speed varient)
|
||||
*/
|
||||
#define ETHERNET_MAX_UDP ( 1500u - 20u - 8u )
|
||||
#define MAX_UDP_RECV ( 0xffff + 16u ) /* allow large frames to be received in the future */
|
||||
@@ -174,20 +176,19 @@ typedef ca_uint32_t caResId;
|
||||
* the common part of each message sent/recv by the
|
||||
* CA server.
|
||||
*/
|
||||
typedef struct ca_hdr {
|
||||
typedef struct ca_hdr {
|
||||
ca_uint16_t m_cmmd; /* operation to be performed */
|
||||
ca_uint16_t m_postsize; /* size of message extension */
|
||||
ca_uint16_t m_dataType; /* operation data type */
|
||||
ca_uint16_t m_postsize; /* size of payload */
|
||||
ca_uint16_t m_dataType; /* operation data type */
|
||||
ca_uint16_t m_count; /* operation data count */
|
||||
ca_uint32_t m_cid; /* channel identifier */
|
||||
ca_uint32_t m_available; /* undefined message location for use
|
||||
* by client processes */
|
||||
}caHdr;
|
||||
ca_uint32_t m_available; /* protocol stub dependent */
|
||||
} caHdr;
|
||||
|
||||
/*
|
||||
* for monitor (event) message extension
|
||||
*/
|
||||
struct mon_info{
|
||||
struct mon_info {
|
||||
ca_float32_t m_lval; /* low delta */
|
||||
ca_float32_t m_hval; /* high delta */
|
||||
ca_float32_t m_toval; /* period btween samples */
|
||||
@@ -195,11 +196,6 @@ struct mon_info{
|
||||
ca_uint16_t m_pad; /* extend to 32 bits */
|
||||
};
|
||||
|
||||
struct monops { /* monitor req opi to ioc */
|
||||
caHdr m_header;
|
||||
struct mon_info m_info;
|
||||
};
|
||||
|
||||
/*
|
||||
* PV names greater than this length assumed to be invalid
|
||||
*/
|
||||
|
||||
+384
-207
File diff suppressed because it is too large
Load Diff
+99
-46
@@ -21,6 +21,7 @@
|
||||
#include "ipAddrToAsciiAsynchronous.h"
|
||||
#include "epicsTimer.h"
|
||||
#include "epicsEvent.h"
|
||||
#include "freeList.h"
|
||||
|
||||
#include "nciu.h"
|
||||
|
||||
@@ -93,6 +94,7 @@ public:
|
||||
|
||||
struct CASG;
|
||||
class inetAddrID;
|
||||
struct caHdrLargeArray;
|
||||
|
||||
class cac : private cacRecycle
|
||||
{
|
||||
@@ -101,7 +103,8 @@ public:
|
||||
virtual ~cac ();
|
||||
|
||||
// beacon management
|
||||
void beaconNotify ( const inetAddrID &addr );
|
||||
void beaconNotify ( const inetAddrID &addr,
|
||||
const epicsTime ¤tTime );
|
||||
void repeaterSubscribeConfirmNotify ();
|
||||
|
||||
// IIU routines
|
||||
@@ -122,7 +125,7 @@ public:
|
||||
void connectAllIO ( nciu &chan );
|
||||
void disconnectAllIO ( nciu &chan );
|
||||
void destroyAllIO ( nciu &chan );
|
||||
void executeResponse ( tcpiiu &, caHdr &, char *pMshBody );
|
||||
bool executeResponse ( tcpiiu &, caHdrLargeArray &, char *pMsgBody );
|
||||
void ioCancel ( nciu &chan, const cacChannel::ioid &id );
|
||||
void ioShow ( const cacChannel::ioid &id, unsigned level ) const;
|
||||
|
||||
@@ -130,8 +133,8 @@ public:
|
||||
bool connectChannel ( unsigned id );
|
||||
void installNetworkChannel ( nciu &, netiiu *&piiu );
|
||||
bool lookupChannelAndTransferToTCP ( unsigned cid, unsigned sid,
|
||||
unsigned typeCode, unsigned long count, unsigned minorVersionNumber,
|
||||
const osiSockAddr & );
|
||||
ca_uint16_t typeCode, arrayElementCount count, unsigned minorVersionNumber,
|
||||
const osiSockAddr &, const epicsTime & currentTime );
|
||||
void uninstallChannel ( nciu & );
|
||||
cacChannel & createChannel ( const char *name_str, cacChannelNotify &chan );
|
||||
void registerService ( cacService &service );
|
||||
@@ -144,7 +147,7 @@ public:
|
||||
cacChannel::ioid readNotifyRequest ( nciu &, unsigned type,
|
||||
unsigned nElem, cacReadNotify & );
|
||||
cacChannel::ioid subscriptionRequest ( nciu &, unsigned type,
|
||||
unsigned long nElem, unsigned mask, cacStateNotify & );
|
||||
arrayElementCount nElem, unsigned mask, cacStateNotify & );
|
||||
|
||||
// sync group routines
|
||||
CASG * lookupCASG ( unsigned id );
|
||||
@@ -154,9 +157,6 @@ public:
|
||||
// exception generation
|
||||
void exception ( int status, const char *pContext,
|
||||
const char *pFileName, unsigned lineNo );
|
||||
void exception ( int status, const char *pContext,
|
||||
unsigned type, unsigned long count,
|
||||
const char *pFileName, unsigned lineNo );
|
||||
|
||||
// callback preemption control
|
||||
void enableCallbackPreemption ();
|
||||
@@ -165,21 +165,30 @@ public:
|
||||
// diagnostics
|
||||
unsigned connectionCount () const;
|
||||
void show ( unsigned level ) const;
|
||||
int printf ( const char *pformat, ... );
|
||||
int vPrintf ( const char *pformat, va_list args );
|
||||
int printf ( const char *pformat, ... ) const;
|
||||
int vPrintf ( const char *pformat, va_list args ) const;
|
||||
void ipAddrToAsciiAsynchronousRequestInstall ( ipAddrToAsciiAsynchronous & request );
|
||||
void signal ( int ca_status, const char *pfilenm,
|
||||
int lineno, const char *pFormat, ... );
|
||||
void vSignal ( int ca_status, const char *pfilenm,
|
||||
int lineno, const char *pFormat, va_list args );
|
||||
|
||||
// misc
|
||||
const char * userNamePointer () const;
|
||||
unsigned getInitializingThreadsPriority () const;
|
||||
|
||||
epicsMutex & mutexRef ();
|
||||
void attachToClientCtx ();
|
||||
char * allocateSmallBufferTCP ();
|
||||
void releaseSmallBufferTCP ( char * );
|
||||
unsigned largeBufferSizeTCP () const;
|
||||
char * allocateLargeBufferTCP ();
|
||||
void releaseLargeBufferTCP ( char * );
|
||||
|
||||
private:
|
||||
ioCounterNet ioCounter;
|
||||
ipAddrToAsciiEngine ipToAEngine;
|
||||
cacServiceList services;
|
||||
tsDLList <tcpiiu> iiuList;
|
||||
tsDLList < tcpiiu > iiuList;
|
||||
chronIntIdResTable
|
||||
< nciu > chanTable;
|
||||
chronIntIdResTable
|
||||
@@ -208,10 +217,13 @@ private:
|
||||
class searchTimer *pSearchTmr;
|
||||
class repeaterSubscribeTimer
|
||||
*pRepeaterSubscribeTmr;
|
||||
void *tcpSmallRecvBufFreeList;
|
||||
void *tcpLargeRecvBufFreeList;
|
||||
cacNotify ¬ify;
|
||||
unsigned ioNotifyInProgressId;
|
||||
unsigned initializingThreadsPriority;
|
||||
unsigned threadsBlockingOnNotifyCompletion;
|
||||
unsigned maxRecvBytesTCP;
|
||||
bool enablePreemptiveCallback;
|
||||
bool ioInProgress;
|
||||
bool setupUDP ();
|
||||
@@ -220,39 +232,57 @@ private:
|
||||
void recycleWriteNotifyIO ( netWriteNotifyIO &io );
|
||||
void recycleSubscription ( netSubscription &io );
|
||||
|
||||
bool ioCompletionNotify ( unsigned id, unsigned type,
|
||||
unsigned long count, const void *pData );
|
||||
bool ioExceptionNotify ( unsigned id,
|
||||
void ioCompletionNotify ( unsigned id, unsigned type,
|
||||
arrayElementCount count, const void *pData );
|
||||
void ioExceptionNotify ( unsigned id,
|
||||
int status, const char *pContext );
|
||||
bool ioExceptionNotify ( unsigned id, int status,
|
||||
const char *pContext, unsigned type, unsigned long count );
|
||||
bool ioCompletionNotifyAndDestroy ( unsigned id );
|
||||
bool ioCompletionNotifyAndDestroy ( unsigned id,
|
||||
unsigned type, unsigned long count, const void *pData );
|
||||
bool ioExceptionNotifyAndDestroy ( unsigned id,
|
||||
void ioExceptionNotify ( unsigned id, int status,
|
||||
const char *pContext, unsigned type, arrayElementCount count );
|
||||
|
||||
void ioCompletionNotifyAndDestroy ( unsigned id );
|
||||
void ioCompletionNotifyAndDestroy ( unsigned id,
|
||||
unsigned type, arrayElementCount count, const void *pData );
|
||||
void ioExceptionNotifyAndDestroy ( unsigned id,
|
||||
int status, const char *pContext );
|
||||
bool ioExceptionNotifyAndDestroy ( unsigned id,
|
||||
int status, const char *pContext, unsigned type, unsigned long count );
|
||||
void ioExceptionNotifyAndDestroy ( unsigned id,
|
||||
int status, const char *pContext, unsigned type, arrayElementCount count );
|
||||
|
||||
// recv protocol stubs
|
||||
bool noopAction ( tcpiiu &, const caHdr &, void *pMsgBdy );
|
||||
bool echoRespAction ( tcpiiu &, const caHdr &, void *pMsgBdy );
|
||||
bool writeNotifyRespAction ( tcpiiu &, const caHdr &, void *pMsgBdy );
|
||||
bool readNotifyRespAction ( tcpiiu &, const caHdr &, void *pMsgBdy );
|
||||
bool eventRespAction ( tcpiiu &, const caHdr &, void *pMsgBdy );
|
||||
bool readRespAction ( tcpiiu &, const caHdr &, void *pMsgBdy );
|
||||
bool clearChannelRespAction ( tcpiiu &, const caHdr &, void *pMsgBdy );
|
||||
bool exceptionRespAction ( tcpiiu &, const caHdr &, void *pMsgBdy );
|
||||
bool accessRightsRespAction ( tcpiiu &, const caHdr &, void *pMsgBdy );
|
||||
bool claimCIURespAction ( tcpiiu &, const caHdr &, void *pMsgBdy );
|
||||
bool verifyAndDisconnectChan ( tcpiiu &, const caHdr &, void *pMsgBdy );
|
||||
bool badTCPRespAction ( tcpiiu &, const caHdr &, void *pMsgBdy );
|
||||
bool noopAction ( tcpiiu &, const caHdrLargeArray &, void *pMsgBdy );
|
||||
bool echoRespAction ( tcpiiu &, const caHdrLargeArray &, void *pMsgBdy );
|
||||
bool writeNotifyRespAction ( tcpiiu &, const caHdrLargeArray &, void *pMsgBdy );
|
||||
bool readNotifyRespAction ( tcpiiu &, const caHdrLargeArray &, void *pMsgBdy );
|
||||
bool eventRespAction ( tcpiiu &, const caHdrLargeArray &, void *pMsgBdy );
|
||||
bool readRespAction ( tcpiiu &, const caHdrLargeArray &, void *pMsgBdy );
|
||||
bool clearChannelRespAction ( tcpiiu &, const caHdrLargeArray &, void *pMsgBdy );
|
||||
bool exceptionRespAction ( tcpiiu &, const caHdrLargeArray &, void *pMsgBdy );
|
||||
bool accessRightsRespAction ( tcpiiu &, const caHdrLargeArray &, void *pMsgBdy );
|
||||
bool claimCIURespAction ( tcpiiu &, const caHdrLargeArray &, void *pMsgBdy );
|
||||
bool verifyAndDisconnectChan ( tcpiiu &, const caHdrLargeArray &, void *pMsgBdy );
|
||||
bool badTCPRespAction ( tcpiiu &, const caHdrLargeArray &, void *pMsgBdy );
|
||||
typedef bool ( cac::*pProtoStubTCP ) (
|
||||
tcpiiu &, const caHdr &, void *pMsgBdy );
|
||||
tcpiiu &, const caHdrLargeArray &, void *pMsgBdy );
|
||||
static const pProtoStubTCP tcpJumpTableCAC [];
|
||||
};
|
||||
|
||||
extern "C" void ca_default_exception_handler ( struct exception_handler_args args );
|
||||
bool defaultExcep ( tcpiiu &iiu, const caHdrLargeArray &hdr,
|
||||
const char *pCtx, unsigned status );
|
||||
bool eventAddExcep ( tcpiiu &iiu, const caHdrLargeArray &hdr,
|
||||
const char *pCtx, unsigned status );
|
||||
bool readExcep ( tcpiiu &iiu, const caHdrLargeArray &hdr,
|
||||
const char *pCtx, unsigned status );
|
||||
bool writeExcep ( tcpiiu &iiu, const caHdrLargeArray &hdr,
|
||||
const char *pCtx, unsigned status );
|
||||
bool clearChanExcep ( tcpiiu &iiu, const caHdrLargeArray &hdr,
|
||||
const char *pCtx, unsigned status );
|
||||
bool readNotifyExcep ( tcpiiu &iiu, const caHdrLargeArray &hdr,
|
||||
const char *pCtx, unsigned status );
|
||||
bool writeNotifyExcep ( tcpiiu &iiu, const caHdrLargeArray &hdr,
|
||||
const char *pCtx, unsigned status );
|
||||
typedef bool ( cac::*pExcepProtoStubTCP ) (
|
||||
tcpiiu &iiu, const caHdrLargeArray &hdr,
|
||||
const char *pCtx, unsigned status );
|
||||
static const pExcepProtoStubTCP tcpExcepJumpTableCAC [];
|
||||
};
|
||||
|
||||
inline const char * cac::userNamePointer () const
|
||||
{
|
||||
@@ -300,18 +330,41 @@ inline void cac::exception ( int status, const char *pContext,
|
||||
this->notify.exception ( status, pContext, pFileName, lineNo );
|
||||
}
|
||||
|
||||
inline void cac::exception ( int status, const char *pContext,
|
||||
unsigned type, unsigned long count,
|
||||
const char *pFileName, unsigned lineNo )
|
||||
{
|
||||
this->notify.exception ( status, pContext, type, count, pFileName, lineNo );
|
||||
}
|
||||
|
||||
inline int cac::vPrintf ( const char *pformat, va_list args )
|
||||
inline int cac::vPrintf ( const char *pformat, va_list args ) const
|
||||
{
|
||||
return this->notify.vPrintf ( pformat, args );
|
||||
}
|
||||
|
||||
inline void cac::attachToClientCtx ()
|
||||
{
|
||||
this->notify.attachToClientCtx ();
|
||||
}
|
||||
|
||||
inline char * cac::allocateSmallBufferTCP ()
|
||||
{
|
||||
return ( char * ) freeListMalloc ( this->tcpSmallRecvBufFreeList );
|
||||
}
|
||||
|
||||
inline void cac::releaseSmallBufferTCP ( char *pBuf )
|
||||
{
|
||||
freeListFree ( this->tcpSmallRecvBufFreeList, pBuf );
|
||||
}
|
||||
|
||||
inline unsigned cac::largeBufferSizeTCP () const
|
||||
{
|
||||
return this->maxRecvBytesTCP;
|
||||
}
|
||||
|
||||
inline char * cac::allocateLargeBufferTCP ()
|
||||
{
|
||||
return ( char * ) freeListMalloc ( this->tcpLargeRecvBufFreeList );
|
||||
}
|
||||
|
||||
inline void cac::releaseLargeBufferTCP ( char *pBuf )
|
||||
{
|
||||
freeListFree ( this->tcpLargeRecvBufFreeList, pBuf );
|
||||
}
|
||||
|
||||
inline bool recvProcessThread::isCurrentThread () const
|
||||
{
|
||||
return this->thread.isCurrentThread ();
|
||||
|
||||
+24
-18
@@ -45,12 +45,16 @@
|
||||
|
||||
class cacChannel;
|
||||
|
||||
// this should not be passing caerr.h status to the exception callback
|
||||
typedef unsigned long arrayElementCount;
|
||||
|
||||
// 1) this should not be passing caerr.h status to the exception callback
|
||||
// 2) needless-to-say the data should be passed here using the new data access API
|
||||
class epicsShareClass cacWriteNotify {
|
||||
public:
|
||||
virtual ~cacWriteNotify () = 0;
|
||||
virtual void completion () = 0;
|
||||
virtual void exception ( int status, const char *pContext ) = 0;
|
||||
virtual void exception ( int status, const char *pContext,
|
||||
unsigned type, arrayElementCount count ) = 0;
|
||||
};
|
||||
|
||||
// 1) this should not be passing caerr.h status to the exception callback
|
||||
@@ -59,9 +63,9 @@ class epicsShareClass cacReadNotify {
|
||||
public:
|
||||
virtual ~cacReadNotify () = 0;
|
||||
virtual void completion ( unsigned type,
|
||||
unsigned long count, const void *pData ) = 0;
|
||||
arrayElementCount count, const void *pData ) = 0;
|
||||
virtual void exception ( int status,
|
||||
const char *pContext, unsigned type, unsigned long count ) = 0;
|
||||
const char *pContext, unsigned type, arrayElementCount count ) = 0;
|
||||
};
|
||||
|
||||
// 1) this should not be passing caerr.h status to the exception callback
|
||||
@@ -70,9 +74,9 @@ class epicsShareClass cacStateNotify {
|
||||
public:
|
||||
virtual ~cacStateNotify () = 0;
|
||||
virtual void current ( unsigned type,
|
||||
unsigned long count, const void *pData ) = 0;
|
||||
arrayElementCount count, const void *pData ) = 0;
|
||||
virtual void exception ( int status,
|
||||
const char *pContext, unsigned type, unsigned long count ) = 0;
|
||||
const char *pContext, unsigned type, arrayElementCount count ) = 0;
|
||||
};
|
||||
|
||||
class caAccessRights {
|
||||
@@ -103,6 +107,10 @@ public:
|
||||
virtual void disconnectNotify () = 0;
|
||||
virtual void accessRightsNotify ( const caAccessRights & ) = 0;
|
||||
virtual void exception ( int status, const char *pContext ) = 0;
|
||||
virtual void readException ( int status, const char *pContext,
|
||||
unsigned type, arrayElementCount count, void *pValue ) = 0;
|
||||
virtual void writeException ( int status, const char *pContext,
|
||||
unsigned type, arrayElementCount count ) = 0;
|
||||
// not for public consumption -- can we get rid of this ????
|
||||
virtual bool includeFirstConnectInCountOfOutstandingIO () const;
|
||||
};
|
||||
@@ -125,21 +133,21 @@ public:
|
||||
virtual const char *pName () const = 0;
|
||||
virtual void show ( unsigned level ) const = 0;
|
||||
virtual void initiateConnect () = 0;
|
||||
virtual void write ( unsigned type, unsigned long count,
|
||||
virtual void write ( unsigned type, arrayElementCount count,
|
||||
const void *pValue ) = 0;
|
||||
// we may need to include an optimization for read copy here if we want to enable
|
||||
// reasonable performance of the old API. Adding it here means that the outstanding IO
|
||||
// count must be visible :-(.
|
||||
virtual ioStatus read ( unsigned type, unsigned long count,
|
||||
virtual ioStatus read ( unsigned type, arrayElementCount count,
|
||||
cacReadNotify &, ioid * = 0 ) = 0;
|
||||
virtual ioStatus write ( unsigned type, unsigned long count,
|
||||
virtual ioStatus write ( unsigned type, arrayElementCount count,
|
||||
const void *pValue, cacWriteNotify &, ioid * = 0 ) = 0;
|
||||
virtual void subscribe ( unsigned type, unsigned long count,
|
||||
virtual void subscribe ( unsigned type, arrayElementCount count,
|
||||
unsigned mask, cacStateNotify &, ioid * = 0 ) = 0;
|
||||
virtual void ioCancel ( const ioid & ) = 0;
|
||||
virtual void ioShow ( const ioid &, unsigned level ) const = 0;
|
||||
virtual short nativeType () const = 0;
|
||||
virtual unsigned long nativeElementCount () const = 0;
|
||||
virtual arrayElementCount nativeElementCount () const = 0;
|
||||
virtual caAccessRights accessRights () const; // defaults to unrestricted access
|
||||
virtual unsigned searchAttempts () const; // defaults to zero
|
||||
virtual double beaconPeriod () const; // defaults to negative DBL_MAX
|
||||
@@ -160,7 +168,7 @@ public:
|
||||
class noReadAccess {};
|
||||
class notConnected {};
|
||||
class unsupportedByService {};
|
||||
class noMemory {};
|
||||
class msgBodyCacheTooSmall {}; // hopefully this one goes away in the future
|
||||
|
||||
private:
|
||||
cacChannelNotify & callback;
|
||||
@@ -169,17 +177,15 @@ private:
|
||||
class cacNotify {
|
||||
public:
|
||||
virtual ~cacNotify () = 0;
|
||||
// exception mechanism needs to be designed
|
||||
virtual void exception ( int status, const char *pContext,
|
||||
const char *pFileName, unsigned lineNo ) = 0;
|
||||
virtual void exception ( int status, const char *pContext,
|
||||
unsigned type, unsigned long count,
|
||||
virtual void exception ( int status, const char *pContext,
|
||||
const char *pFileName, unsigned lineNo ) = 0;
|
||||
// perhaps this should be phased out in deference to the exception mechanism
|
||||
virtual int vPrintf ( const char *pformat, va_list args ) = 0;
|
||||
virtual int vPrintf ( const char *pformat, va_list args ) const = 0;
|
||||
// this should probably be phased out (its not OS independent)
|
||||
virtual void fdWasCreated ( int fd ) = 0;
|
||||
virtual void fdWasDestroyed ( int fd ) = 0;
|
||||
// backwards compatibility
|
||||
virtual void attachToClientCtx () = 0;
|
||||
};
|
||||
|
||||
struct cacService : public tsDLNode < cacService > {
|
||||
|
||||
+1
-1
@@ -142,7 +142,7 @@ READONLY char *ca_message_text[]
|
||||
"Unable to allocate additional dynamic memory",
|
||||
"Unknown IO channel",
|
||||
"Record field specified inappropriate for channel specified",
|
||||
"The array or data structure specified will not fit in CA message buffer",
|
||||
"The array or data structure specified is less than EPICS_CA_MAX_ARRAY_BYTES",
|
||||
"User specified timeout on IO operation expired",
|
||||
"Sorry, that feature is planned but not supported at this time",
|
||||
"The supplied string is unusually large",
|
||||
|
||||
+6
-6
@@ -29,8 +29,8 @@ int main ( int, char ** )
|
||||
char buf [0x4000];
|
||||
const char *pCurBuf;
|
||||
const caHdr *pCurMsg;
|
||||
unsigned serverPort;
|
||||
unsigned repeaterPort;
|
||||
ca_uint16_t serverPort;
|
||||
ca_uint16_t repeaterPort;
|
||||
int status;
|
||||
|
||||
serverPort =
|
||||
@@ -151,13 +151,14 @@ int main ( int, char ** )
|
||||
}
|
||||
|
||||
bool netChange;
|
||||
epicsTime currentTime = epicsTime::getCurrent();
|
||||
|
||||
/*
|
||||
* look for it in the hash table
|
||||
*/
|
||||
bhe *pBHE = beaconTable.lookup ( ina );
|
||||
if ( pBHE ) {
|
||||
netChange = pBHE->updatePeriod ( programBeginTime );
|
||||
netChange = pBHE->updatePeriod ( programBeginTime, currentTime );
|
||||
}
|
||||
else {
|
||||
/*
|
||||
@@ -168,7 +169,7 @@ int main ( int, char ** )
|
||||
* shortly after the program started up)
|
||||
*/
|
||||
netChange = false;
|
||||
pBHE = new bhe ( epicsTime::getCurrent (), ina );
|
||||
pBHE = new bhe ( currentTime, ina );
|
||||
if ( pBHE ) {
|
||||
if ( beaconTable.add ( *pBHE ) < 0 ) {
|
||||
pBHE->destroy ();
|
||||
@@ -178,8 +179,7 @@ int main ( int, char ** )
|
||||
|
||||
if ( netChange ) {
|
||||
char date[64];
|
||||
epicsTime current = epicsTime::getCurrent ();
|
||||
current.strftime ( date, sizeof ( date ), "%a %b %d %Y %H:%M:%S");
|
||||
currentTime.strftime ( date, sizeof ( date ), "%a %b %d %Y %H:%M:%S");
|
||||
char host[64];
|
||||
ipAddrToA ( &ina, host, sizeof ( host ) );
|
||||
printf ("CA server beacon anomaly: %s %s\n", date, host );
|
||||
|
||||
+4
-2
@@ -49,13 +49,13 @@ typedef void tf ( ti *pItems, unsigned iterations, unsigned *pInlineIter );
|
||||
* test_pend()
|
||||
*/
|
||||
LOCAL void test_pend(
|
||||
ti *pItems,
|
||||
ti *pItems,
|
||||
unsigned iterations,
|
||||
unsigned *pInlineIter
|
||||
)
|
||||
{
|
||||
unsigned i;
|
||||
int status;
|
||||
int status;
|
||||
|
||||
for (i=0; i<iterations; i++) {
|
||||
status = ca_pend_event(1e-9);
|
||||
@@ -107,6 +107,7 @@ unsigned *pInlineIter
|
||||
/*
|
||||
* test_sync_search()
|
||||
*/
|
||||
#if 0
|
||||
LOCAL void test_sync_search(
|
||||
ti *pItems,
|
||||
unsigned iterations,
|
||||
@@ -125,6 +126,7 @@ unsigned *pInlineIter
|
||||
|
||||
*pInlineIter = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* test_free ()
|
||||
|
||||
+85
-41
@@ -17,6 +17,8 @@
|
||||
#ifndef comBufh
|
||||
#define comBufh
|
||||
|
||||
#include <new>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "epicsAssert.h"
|
||||
@@ -31,6 +33,7 @@ class wireSendAdapter {
|
||||
public:
|
||||
virtual unsigned sendBytes ( const void *pBuf,
|
||||
unsigned nBytesInBuf ) = 0;
|
||||
virtual void forcedShutdown () = 0;
|
||||
};
|
||||
|
||||
class wireRecvAdapter {
|
||||
@@ -62,17 +65,20 @@ public:
|
||||
unsigned copyOutBytes ( void *pBuf, unsigned nBytes );
|
||||
bool copyOutAllBytes ( void *pBuf, unsigned nBytes );
|
||||
unsigned removeBytes ( unsigned nBytes );
|
||||
void * operator new ( size_t size );
|
||||
void * operator new ( size_t size, const std::nothrow_t & );
|
||||
void operator delete ( void *pCadaver, size_t size );
|
||||
bool flushToWire ( wireSendAdapter & );
|
||||
unsigned fillFromWire ( wireRecvAdapter & );
|
||||
epicsUInt8 getByte ();
|
||||
class insufficentBytesAvailable {};
|
||||
protected:
|
||||
~comBuf ();
|
||||
private:
|
||||
unsigned nextWriteIndex;
|
||||
unsigned nextReadIndex;
|
||||
unsigned char buf [ comBufSize ]; // optimal for 100 Mb Ethernet LAN MTU
|
||||
unsigned clipNElem ( unsigned elemSize, unsigned nElem );
|
||||
epicsUInt8 buf [ comBufSize ];
|
||||
unsigned unoccupiedElem ( unsigned elemSize, unsigned nElem );
|
||||
unsigned occupiedElem ( unsigned elemSize, unsigned nElem );
|
||||
static tsFreeList < class comBuf, 0x20 > freeList;
|
||||
static epicsMutex freeListMutex;
|
||||
};
|
||||
@@ -90,7 +96,7 @@ inline void comBuf::destroy ()
|
||||
delete this;
|
||||
}
|
||||
|
||||
inline void * comBuf::operator new ( size_t size )
|
||||
inline void * comBuf::operator new ( size_t size, const std::nothrow_t & )
|
||||
{
|
||||
epicsAutoMutex locker ( comBuf::freeListMutex );
|
||||
return comBuf::freeList.allocate ( size );
|
||||
@@ -109,17 +115,18 @@ inline unsigned comBuf::unoccupiedBytes () const
|
||||
|
||||
inline unsigned comBuf::occupiedBytes () const
|
||||
{
|
||||
// assert (this->nextWriteIndex >= this->nextReadIndex);
|
||||
return this->nextWriteIndex - this->nextReadIndex;
|
||||
}
|
||||
|
||||
inline bool comBuf::copyInAllBytes ( const void *pBuf, unsigned nBytes )
|
||||
{
|
||||
if ( nBytes > this->unoccupiedBytes () ) {
|
||||
return false;
|
||||
if ( nBytes <= this->unoccupiedBytes () ) {
|
||||
memcpy ( &this->buf[this->nextWriteIndex], pBuf, nBytes);
|
||||
this->nextWriteIndex += nBytes;
|
||||
return true;
|
||||
}
|
||||
memcpy ( &this->buf[this->nextWriteIndex], pBuf, nBytes);
|
||||
this->nextWriteIndex += nBytes;
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
inline unsigned comBuf::copyInBytes ( const void *pBuf, unsigned nBytes )
|
||||
@@ -145,12 +152,12 @@ inline unsigned comBuf::copyIn ( comBuf &bufIn )
|
||||
|
||||
inline bool comBuf::copyOutAllBytes ( void *pBuf, unsigned nBytes )
|
||||
{
|
||||
if ( nBytes > this->occupiedBytes () ) {
|
||||
return false;
|
||||
if ( nBytes <= this->occupiedBytes () ) {
|
||||
memcpy ( pBuf, &this->buf[this->nextReadIndex], nBytes);
|
||||
this->nextReadIndex += nBytes;
|
||||
return true;
|
||||
}
|
||||
memcpy ( pBuf, &this->buf[this->nextReadIndex], nBytes);
|
||||
this->nextReadIndex += nBytes;
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
inline unsigned comBuf::copyOutBytes ( void *pBuf, unsigned nBytes )
|
||||
@@ -197,7 +204,7 @@ inline unsigned comBuf::fillFromWire ( wireRecvAdapter &wire )
|
||||
return nNewBytes;
|
||||
}
|
||||
|
||||
inline unsigned comBuf::clipNElem ( unsigned elemSize, unsigned nElem )
|
||||
inline unsigned comBuf::unoccupiedElem ( unsigned elemSize, unsigned nElem )
|
||||
{
|
||||
unsigned avail = this->unoccupiedBytes ();
|
||||
if ( elemSize * nElem > avail ) {
|
||||
@@ -218,75 +225,112 @@ 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 );
|
||||
nElem = this->unoccupiedElem ( sizeof (*pValue), nElem );
|
||||
for ( unsigned i = 0u; i < nElem; i++ ) {
|
||||
this->buf[this->nextWriteIndex++] = pValue[i] >> 8u;
|
||||
this->buf[this->nextWriteIndex++] = pValue[i] >> 0u;
|
||||
this->buf[this->nextWriteIndex++] =
|
||||
static_cast < char > ( pValue[i] >> 8u );
|
||||
this->buf[this->nextWriteIndex++] =
|
||||
static_cast < char > ( pValue[i] >> 0u );
|
||||
}
|
||||
return nElem;
|
||||
}
|
||||
|
||||
inline unsigned comBuf::copyIn ( const epicsUInt16 *pValue, unsigned nElem )
|
||||
{
|
||||
nElem = this->clipNElem ( sizeof (*pValue), nElem );
|
||||
nElem = this->unoccupiedElem ( sizeof (*pValue), nElem );
|
||||
for ( unsigned i = 0u; i < nElem; i++ ) {
|
||||
this->buf[this->nextWriteIndex++] = pValue[i] >> 8u;
|
||||
this->buf[this->nextWriteIndex++] = pValue[i] >> 0u;
|
||||
this->buf[this->nextWriteIndex++] =
|
||||
static_cast < char > ( pValue[i] >> 8u );
|
||||
this->buf[this->nextWriteIndex++] =
|
||||
static_cast < char > ( pValue[i] >> 0u );
|
||||
}
|
||||
return nElem;
|
||||
}
|
||||
|
||||
inline unsigned comBuf::copyIn ( const epicsInt32 *pValue, unsigned nElem )
|
||||
{
|
||||
nElem = this->clipNElem ( sizeof (*pValue), nElem );
|
||||
nElem = this->unoccupiedElem ( 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;
|
||||
this->buf[this->nextWriteIndex++] =
|
||||
static_cast < char > ( pValue[i] >> 24u );
|
||||
this->buf[this->nextWriteIndex++] =
|
||||
static_cast < char > ( pValue[i] >> 16u );
|
||||
this->buf[this->nextWriteIndex++] =
|
||||
static_cast < char > ( pValue[i] >> 8u );
|
||||
this->buf[this->nextWriteIndex++] =
|
||||
static_cast < char > ( pValue[i] >> 0u );
|
||||
}
|
||||
return nElem;
|
||||
}
|
||||
|
||||
inline unsigned comBuf::copyIn ( const epicsUInt32 *pValue, unsigned nElem )
|
||||
{
|
||||
nElem = this->clipNElem ( sizeof (*pValue), nElem );
|
||||
nElem = this->unoccupiedElem ( 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;
|
||||
this->buf[this->nextWriteIndex++] =
|
||||
static_cast < char > ( pValue[i] >> 24u );
|
||||
this->buf[this->nextWriteIndex++] =
|
||||
static_cast < char > ( pValue[i] >> 16u );
|
||||
this->buf[this->nextWriteIndex++] =
|
||||
static_cast < char > ( pValue[i] >> 8u );
|
||||
this->buf[this->nextWriteIndex++] =
|
||||
static_cast < char > ( pValue[i] >> 0u );
|
||||
}
|
||||
return nElem;
|
||||
}
|
||||
|
||||
inline unsigned comBuf::copyIn ( const epicsFloat32 *pValue, unsigned nElem )
|
||||
{
|
||||
nElem = this->clipNElem ( sizeof (*pValue), nElem );
|
||||
nElem = this->unoccupiedElem ( 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;
|
||||
this->nextWriteIndex += sizeof ( *pValue );
|
||||
}
|
||||
return nElem;
|
||||
}
|
||||
|
||||
inline unsigned comBuf::copyIn ( const epicsFloat64 *pValue, unsigned nElem )
|
||||
{
|
||||
nElem = this->clipNElem ( sizeof (*pValue), nElem );
|
||||
nElem = this->unoccupiedElem ( 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;
|
||||
this->nextWriteIndex += sizeof ( *pValue );
|
||||
}
|
||||
return nElem;
|
||||
}
|
||||
|
||||
#endif // comBuf
|
||||
inline unsigned comBuf::copyIn ( const epicsOldString *pValue, unsigned nElem )
|
||||
{
|
||||
nElem = this->unoccupiedElem ( sizeof (*pValue), nElem );
|
||||
unsigned size = nElem * sizeof ( *pValue );
|
||||
memcpy ( &this->buf[ this->nextWriteIndex ], pValue, size );
|
||||
this->nextWriteIndex += size;
|
||||
return nElem;
|
||||
}
|
||||
|
||||
inline unsigned comBuf::occupiedElem ( unsigned elemSize, unsigned nElem )
|
||||
{
|
||||
unsigned avail = this->occupiedBytes ();
|
||||
if ( elemSize * nElem > avail ) {
|
||||
return avail / elemSize;
|
||||
}
|
||||
else {
|
||||
return nElem;
|
||||
}
|
||||
}
|
||||
|
||||
inline epicsUInt8 comBuf::getByte ()
|
||||
{
|
||||
if ( this->occupiedBytes () ) {
|
||||
return this->buf[ this->nextReadIndex++ ];
|
||||
}
|
||||
else {
|
||||
throw insufficentBytesAvailable ();
|
||||
}
|
||||
}
|
||||
|
||||
#endif // ifndef comBufh
|
||||
|
||||
+47
-11
@@ -59,27 +59,47 @@ unsigned comQueRecv::occupiedBytes () const
|
||||
return nBytes;
|
||||
}
|
||||
|
||||
bool comQueRecv::copyOutBytes ( void *pBuf, unsigned nBytes )
|
||||
unsigned comQueRecv::copyOutBytes ( void *pBuf, unsigned nBytes )
|
||||
{
|
||||
char *pCharBuf = static_cast < char * > ( pBuf );
|
||||
|
||||
// dont return partial message
|
||||
if ( nBytes > this->occupiedBytes () ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned bytesLeft = nBytes;
|
||||
while ( bytesLeft ) {
|
||||
unsigned totalBytes = 0u;
|
||||
do {
|
||||
comBuf * pComBuf = this->bufs.first ();
|
||||
assert ( pComBuf );
|
||||
bytesLeft -= pComBuf->copyOutBytes ( &pCharBuf[nBytes-bytesLeft], bytesLeft );
|
||||
if ( ! pComBuf ) {
|
||||
return totalBytes;
|
||||
}
|
||||
totalBytes += pComBuf->copyOutBytes ( &pCharBuf[totalBytes], nBytes - totalBytes );
|
||||
if ( pComBuf->occupiedBytes () == 0u ) {
|
||||
this->bufs.remove ( *pComBuf );
|
||||
pComBuf->destroy ();
|
||||
}
|
||||
}
|
||||
while ( totalBytes < nBytes );
|
||||
return totalBytes;
|
||||
}
|
||||
|
||||
return true;
|
||||
unsigned comQueRecv::removeBytes ( unsigned nBytes )
|
||||
{
|
||||
unsigned totalBytes = 0u;
|
||||
unsigned bytesLeft = nBytes;
|
||||
while ( bytesLeft ) {
|
||||
comBuf * pComBuf = this->bufs.first ();
|
||||
if ( ! pComBuf ) {
|
||||
return totalBytes;
|
||||
}
|
||||
unsigned nBytes = pComBuf->removeBytes ( bytesLeft );
|
||||
if ( pComBuf->occupiedBytes () == 0u ) {
|
||||
this->bufs.remove ( *pComBuf );
|
||||
pComBuf->destroy ();
|
||||
}
|
||||
if ( nBytes == 0u) {
|
||||
return totalBytes;
|
||||
}
|
||||
totalBytes += nBytes;
|
||||
bytesLeft = nBytes - totalBytes;
|
||||
}
|
||||
return nBytes;
|
||||
}
|
||||
|
||||
void comQueRecv::pushLastComBufReceived ( comBuf & bufIn )
|
||||
@@ -98,3 +118,19 @@ void comQueRecv::pushLastComBufReceived ( comBuf & bufIn )
|
||||
}
|
||||
}
|
||||
|
||||
epicsUInt8 comQueRecv::popUInt8 ()
|
||||
{
|
||||
comBuf *pComBuf = this->bufs.first ();
|
||||
if ( pComBuf ) {
|
||||
epicsUInt8 tmp = pComBuf->getByte ();
|
||||
if ( pComBuf->occupiedBytes() == 0u ) {
|
||||
this->bufs.remove ( *pComBuf );
|
||||
pComBuf->destroy ();
|
||||
}
|
||||
return tmp;
|
||||
}
|
||||
throw insufficentBytesAvailable ();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
+6
-36
@@ -87,66 +87,36 @@ void comQueSend::clear ()
|
||||
this->nBytesPending -= pBuf->occupiedBytes ();
|
||||
pBuf->destroy ();
|
||||
}
|
||||
this->reservoir.drain ();
|
||||
}
|
||||
|
||||
|
||||
// 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)
|
||||
void comQueSend::reserveSpace ( unsigned msgSize )
|
||||
{
|
||||
unsigned bytesReserved;
|
||||
|
||||
bytesReserved = this->reservoir.nBytes ();
|
||||
|
||||
comBuf *pComBuf = this->bufs.last ();
|
||||
if ( pComBuf ) {
|
||||
bytesReserved += pComBuf->unoccupiedBytes ();
|
||||
}
|
||||
|
||||
while ( bytesReserved < msgSize ) {
|
||||
reservoir.addOneBuffer ();
|
||||
bytesReserved += comBuf::capacityBytes ();
|
||||
}
|
||||
}
|
||||
|
||||
void comQueSend::copy_dbr_string ( const void *pValue, unsigned nElem )
|
||||
{
|
||||
comQueSend_copyIn ( this->nBytesPending, this->bufs, this->reservoir,
|
||||
static_cast <const dbr_string_t *> ( pValue ), nElem );
|
||||
this->copyIn ( static_cast <const dbr_string_t *> ( pValue ), nElem );
|
||||
}
|
||||
|
||||
void comQueSend::copy_dbr_short ( const void *pValue, unsigned nElem )
|
||||
{
|
||||
comQueSend_copyIn ( this->nBytesPending, this->bufs, this->reservoir,
|
||||
static_cast <const dbr_short_t *> ( pValue ), nElem );
|
||||
this->copyIn ( static_cast <const dbr_short_t *> ( pValue ), nElem );
|
||||
}
|
||||
|
||||
void comQueSend::copy_dbr_float ( const void *pValue, unsigned nElem )
|
||||
{
|
||||
comQueSend_copyIn ( this->nBytesPending, this->bufs, this->reservoir,
|
||||
static_cast <const dbr_float_t *> ( pValue ), nElem );
|
||||
this->copyIn ( static_cast <const dbr_float_t *> ( pValue ), nElem );
|
||||
}
|
||||
|
||||
void comQueSend::copy_dbr_char ( const void *pValue, unsigned nElem )
|
||||
{
|
||||
comQueSend_copyIn ( this->nBytesPending, this->bufs, this->reservoir,
|
||||
static_cast <const dbr_char_t *> ( pValue ), nElem );
|
||||
this->copyIn ( static_cast <const dbr_char_t *> ( pValue ), nElem );
|
||||
}
|
||||
|
||||
void comQueSend::copy_dbr_long ( const void *pValue, unsigned nElem )
|
||||
{
|
||||
comQueSend_copyIn ( this->nBytesPending, this->bufs, this->reservoir,
|
||||
static_cast <const dbr_long_t *> ( pValue ), nElem );
|
||||
this->copyIn ( static_cast <const dbr_long_t *> ( pValue ), nElem );
|
||||
}
|
||||
|
||||
void comQueSend::copy_dbr_double ( const void *pValue, unsigned nElem )
|
||||
{
|
||||
comQueSend_copyIn ( this->nBytesPending, this->bufs, this->reservoir,
|
||||
static_cast <const dbr_double_t *> ( pValue ), nElem );
|
||||
this->copyIn ( static_cast <const dbr_double_t *> ( pValue ), nElem );
|
||||
}
|
||||
|
||||
const comQueSend::copyFunc_t comQueSend::dbrCopyVector [39] = {
|
||||
|
||||
+163
-161
@@ -21,6 +21,8 @@
|
||||
#include "iocinf.h"
|
||||
#include "caProto.h"
|
||||
|
||||
typedef unsigned long arrayElementCount;
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include "net_convert.h"
|
||||
|
||||
@@ -55,10 +57,10 @@
|
||||
*
|
||||
*/
|
||||
LOCAL void cvrt_string(
|
||||
const void *s, /* source */
|
||||
void *d, /* destination */
|
||||
int encode, /* cvrt HOST to NET if T */
|
||||
unsigned long num /* number of values */
|
||||
const void *s, /* source */
|
||||
void *d, /* destination */
|
||||
int encode, /* cvrt HOST to NET if T */
|
||||
arrayElementCount num /* number of values */
|
||||
)
|
||||
{
|
||||
char *pSrc = (char *) s;
|
||||
@@ -79,15 +81,15 @@ unsigned long num /* number of values */
|
||||
* CVRT_SHORT()
|
||||
*/
|
||||
LOCAL void cvrt_short(
|
||||
const void *s, /* source */
|
||||
void *d, /* destination */
|
||||
int encode, /* cvrt HOST to NET if T */
|
||||
unsigned long num /* number of values */
|
||||
const void *s, /* source */
|
||||
void *d, /* destination */
|
||||
int encode, /* cvrt HOST to NET if T */
|
||||
arrayElementCount num /* number of values */
|
||||
)
|
||||
{
|
||||
dbr_short_t *pSrc = (dbr_short_t *) s;
|
||||
dbr_short_t *pDest = (dbr_short_t *) d;
|
||||
unsigned long i;
|
||||
dbr_short_t *pSrc = (dbr_short_t *) s;
|
||||
dbr_short_t *pDest = (dbr_short_t *) d;
|
||||
arrayElementCount i;
|
||||
|
||||
for(i=0; i<num; i++){
|
||||
*pDest = dbr_ntohs( *pSrc );
|
||||
@@ -107,15 +109,15 @@ unsigned long num /* number of values */
|
||||
*
|
||||
*/
|
||||
LOCAL void cvrt_char(
|
||||
const void *s, /* source */
|
||||
void *d, /* destination */
|
||||
int encode, /* cvrt HOST to NET if T */
|
||||
unsigned long num /* number of values */
|
||||
const void *s, /* source */
|
||||
void *d, /* destination */
|
||||
int encode, /* cvrt HOST to NET if T */
|
||||
arrayElementCount num /* number of values */
|
||||
)
|
||||
{
|
||||
unsigned long i;
|
||||
dbr_char_t *pSrc = (dbr_char_t *) s;
|
||||
dbr_char_t *pDest = (dbr_char_t *) d;
|
||||
arrayElementCount i;
|
||||
dbr_char_t *pSrc = (dbr_char_t *) s;
|
||||
dbr_char_t *pDest = (dbr_char_t *) d;
|
||||
|
||||
/* convert "in place" -> nothing to do */
|
||||
if (s == d)
|
||||
@@ -129,15 +131,15 @@ unsigned long num /* number of values */
|
||||
* CVRT_LONG()
|
||||
*/
|
||||
LOCAL void cvrt_long(
|
||||
const void *s, /* source */
|
||||
void *d, /* destination */
|
||||
int encode, /* cvrt HOST to NET if T */
|
||||
unsigned long num /* number of values */
|
||||
const void *s, /* source */
|
||||
void *d, /* destination */
|
||||
int encode, /* cvrt HOST to NET if T */
|
||||
arrayElementCount num /* number of values */
|
||||
)
|
||||
{
|
||||
unsigned long i;
|
||||
dbr_long_t *pSrc = (dbr_long_t *) s;
|
||||
dbr_long_t *pDest = (dbr_long_t *) d;
|
||||
arrayElementCount i;
|
||||
dbr_long_t *pSrc = (dbr_long_t *) s;
|
||||
dbr_long_t *pDest = (dbr_long_t *) d;
|
||||
|
||||
for(i=0; i<num; i++){
|
||||
*pDest = dbr_ntohl( *pSrc );
|
||||
@@ -157,15 +159,15 @@ unsigned long num /* number of values */
|
||||
*
|
||||
*/
|
||||
LOCAL void cvrt_enum(
|
||||
const void *s, /* source */
|
||||
void *d, /* destination */
|
||||
int encode, /* cvrt HOST to NET if T */
|
||||
unsigned long num /* number of values */
|
||||
const void *s, /* source */
|
||||
void *d, /* destination */
|
||||
int encode, /* cvrt HOST to NET if T */
|
||||
arrayElementCount num /* number of values */
|
||||
)
|
||||
{
|
||||
unsigned long i;
|
||||
dbr_enum_t *pSrc;
|
||||
dbr_enum_t *pDest;
|
||||
arrayElementCount i;
|
||||
dbr_enum_t *pSrc;
|
||||
dbr_enum_t *pDest;
|
||||
|
||||
pSrc = (dbr_enum_t *) s;
|
||||
pDest = (dbr_enum_t *) d;
|
||||
@@ -189,15 +191,15 @@ unsigned long num /* number of values */
|
||||
*
|
||||
*/
|
||||
LOCAL void cvrt_float(
|
||||
const void *s, /* source */
|
||||
void *d, /* destination */
|
||||
int encode, /* cvrt HOST to NET if T */
|
||||
unsigned long num /* number of values */
|
||||
const void *s, /* source */
|
||||
void *d, /* destination */
|
||||
int encode, /* cvrt HOST to NET if T */
|
||||
arrayElementCount num /* number of values */
|
||||
)
|
||||
{
|
||||
unsigned long i;
|
||||
dbr_float_t *pSrc = (dbr_float_t *) s;
|
||||
dbr_float_t *pDest = (dbr_float_t *) d;
|
||||
arrayElementCount i;
|
||||
dbr_float_t *pSrc = (dbr_float_t *) s;
|
||||
dbr_float_t *pDest = (dbr_float_t *) d;
|
||||
|
||||
for(i=0; i<num; i++){
|
||||
if(encode){
|
||||
@@ -218,15 +220,15 @@ unsigned long num /* number of values */
|
||||
* CVRT_DOUBLE()
|
||||
*/
|
||||
LOCAL void cvrt_double(
|
||||
const void *s, /* source */
|
||||
void *d, /* destination */
|
||||
int encode, /* cvrt HOST to NET if T */
|
||||
unsigned long num /* number of values */
|
||||
const void *s, /* source */
|
||||
void *d, /* destination */
|
||||
int encode, /* cvrt HOST to NET if T */
|
||||
arrayElementCount num /* number of values */
|
||||
)
|
||||
{
|
||||
unsigned long i;
|
||||
dbr_double_t *pSrc = (dbr_double_t *) s;
|
||||
dbr_double_t *pDest = (dbr_double_t *) d;
|
||||
arrayElementCount i;
|
||||
dbr_double_t *pSrc = (dbr_double_t *) s;
|
||||
dbr_double_t *pDest = (dbr_double_t *) d;
|
||||
|
||||
for(i=0; i<num; i++){
|
||||
if(encode){
|
||||
@@ -257,10 +259,10 @@ unsigned long num /* number of values */
|
||||
****************************************************************************/
|
||||
|
||||
LOCAL void cvrt_sts_string(
|
||||
const void *s, /* source */
|
||||
void *d, /* destination */
|
||||
int encode, /* cvrt HOST to NET if T */
|
||||
unsigned long num /* number of values */
|
||||
const void *s, /* source */
|
||||
void *d, /* destination */
|
||||
int encode, /* cvrt HOST to NET if T */
|
||||
arrayElementCount num /* number of values */
|
||||
)
|
||||
{
|
||||
struct dbr_sts_string *pSrc = (struct dbr_sts_string *) s;
|
||||
@@ -295,10 +297,10 @@ unsigned long num /* number of values */
|
||||
****************************************************************************/
|
||||
|
||||
LOCAL void cvrt_sts_short(
|
||||
const void *s, /* source */
|
||||
void *d, /* destination */
|
||||
int encode, /* cvrt HOST to NET if T */
|
||||
unsigned long num /* number of values */
|
||||
const void *s, /* source */
|
||||
void *d, /* destination */
|
||||
int encode, /* cvrt HOST to NET if T */
|
||||
arrayElementCount num /* number of values */
|
||||
)
|
||||
{
|
||||
struct dbr_sts_int *pSrc = (struct dbr_sts_int *) s;
|
||||
@@ -330,10 +332,10 @@ unsigned long num /* number of values */
|
||||
****************************************************************************/
|
||||
|
||||
LOCAL void cvrt_sts_float(
|
||||
const void *s, /* source */
|
||||
void *d, /* destination */
|
||||
int encode, /* cvrt HOST to NET if T */
|
||||
unsigned long num /* number of values */
|
||||
const void *s, /* source */
|
||||
void *d, /* destination */
|
||||
int encode, /* cvrt HOST to NET if T */
|
||||
arrayElementCount num /* number of values */
|
||||
)
|
||||
{
|
||||
struct dbr_sts_float *pSrc = (struct dbr_sts_float *) s;
|
||||
@@ -356,10 +358,10 @@ unsigned long num /* number of values */
|
||||
****************************************************************************/
|
||||
|
||||
LOCAL void cvrt_sts_double(
|
||||
const void *s, /* source */
|
||||
void *d, /* destination */
|
||||
int encode, /* cvrt HOST to NET if T */
|
||||
unsigned long num /* number of values */
|
||||
const void *s, /* source */
|
||||
void *d, /* destination */
|
||||
int encode, /* cvrt HOST to NET if T */
|
||||
arrayElementCount num /* number of values */
|
||||
)
|
||||
{
|
||||
struct dbr_sts_double *pSrc = (struct dbr_sts_double *) s;
|
||||
@@ -385,10 +387,10 @@ unsigned long num /* number of values */
|
||||
****************************************************************************/
|
||||
|
||||
LOCAL void cvrt_sts_enum(
|
||||
const void *s, /* source */
|
||||
void *d, /* destination */
|
||||
int encode, /* cvrt HOST to NET if T */
|
||||
unsigned long num /* number of values */
|
||||
const void *s, /* source */
|
||||
void *d, /* destination */
|
||||
int encode, /* cvrt HOST to NET if T */
|
||||
arrayElementCount num /* number of values */
|
||||
)
|
||||
{
|
||||
struct dbr_sts_enum *pSrc = (struct dbr_sts_enum *) s;
|
||||
@@ -413,10 +415,10 @@ unsigned long num /* number of values */
|
||||
****************************************************************************/
|
||||
|
||||
LOCAL void cvrt_gr_short(
|
||||
const void *s, /* source */
|
||||
void *d, /* destination */
|
||||
int encode, /* cvrt HOST to NET if T */
|
||||
unsigned long num /* number of values */
|
||||
const void *s, /* source */
|
||||
void *d, /* destination */
|
||||
int encode, /* cvrt HOST to NET if T */
|
||||
arrayElementCount num /* number of values */
|
||||
)
|
||||
{
|
||||
struct dbr_gr_int *pSrc = (struct dbr_gr_int *) s;
|
||||
@@ -450,10 +452,10 @@ unsigned long num /* number of values */
|
||||
****************************************************************************/
|
||||
|
||||
LOCAL void cvrt_gr_char(
|
||||
const void *s, /* source */
|
||||
void *d, /* destination */
|
||||
int encode, /* cvrt HOST to NET if T */
|
||||
unsigned long num /* number of values */
|
||||
const void *s, /* source */
|
||||
void *d, /* destination */
|
||||
int encode, /* cvrt HOST to NET if T */
|
||||
arrayElementCount num /* number of values */
|
||||
)
|
||||
{
|
||||
struct dbr_gr_char *pSrc = (struct dbr_gr_char *) s;
|
||||
@@ -491,10 +493,10 @@ unsigned long num /* number of values */
|
||||
****************************************************************************/
|
||||
|
||||
LOCAL void cvrt_gr_long(
|
||||
const void *s, /* source */
|
||||
void *d, /* destination */
|
||||
int encode, /* cvrt HOST to NET if T */
|
||||
unsigned long num /* number of values */
|
||||
const void *s, /* source */
|
||||
void *d, /* destination */
|
||||
int encode, /* cvrt HOST to NET if T */
|
||||
arrayElementCount num /* number of values */
|
||||
)
|
||||
{
|
||||
struct dbr_gr_long *pSrc = (struct dbr_gr_long *) s;
|
||||
@@ -529,10 +531,10 @@ unsigned long num /* number of values */
|
||||
****************************************************************************/
|
||||
|
||||
LOCAL void cvrt_gr_enum(
|
||||
const void *s, /* source */
|
||||
void *d, /* destination */
|
||||
int encode, /* cvrt HOST to NET if T */
|
||||
unsigned long num /* number of values */
|
||||
const void *s, /* source */
|
||||
void *d, /* destination */
|
||||
int encode, /* cvrt HOST to NET if T */
|
||||
arrayElementCount num /* number of values */
|
||||
)
|
||||
{
|
||||
struct dbr_gr_enum *pSrc = (struct dbr_gr_enum *) s;
|
||||
@@ -562,10 +564,10 @@ unsigned long num /* number of values */
|
||||
****************************************************************************/
|
||||
|
||||
LOCAL void cvrt_gr_double(
|
||||
const void *s, /* source */
|
||||
void *d, /* destination */
|
||||
int encode, /* cvrt HOST to NET if T */
|
||||
unsigned long num /* number of values */
|
||||
const void *s, /* source */
|
||||
void *d, /* destination */
|
||||
int encode, /* cvrt HOST to NET if T */
|
||||
arrayElementCount num /* number of values */
|
||||
)
|
||||
{
|
||||
struct dbr_gr_double *pSrc = (struct dbr_gr_double *) s;
|
||||
@@ -624,10 +626,10 @@ unsigned long num /* number of values */
|
||||
****************************************************************************/
|
||||
|
||||
LOCAL void cvrt_gr_float(
|
||||
const void *s, /* source */
|
||||
void *d, /* destination */
|
||||
int encode, /* cvrt HOST to NET if T */
|
||||
unsigned long num /* number of values */
|
||||
const void *s, /* source */
|
||||
void *d, /* destination */
|
||||
int encode, /* cvrt HOST to NET if T */
|
||||
arrayElementCount num /* number of values */
|
||||
)
|
||||
{
|
||||
struct dbr_gr_float *pSrc = (struct dbr_gr_float *) s;
|
||||
@@ -687,10 +689,10 @@ unsigned long num /* number of values */
|
||||
****************************************************************************/
|
||||
|
||||
LOCAL void cvrt_ctrl_short(
|
||||
const void *s, /* source */
|
||||
void *d, /* destination */
|
||||
int encode, /* cvrt HOST to NET if T */
|
||||
unsigned long num /* number of values */
|
||||
const void *s, /* source */
|
||||
void *d, /* destination */
|
||||
int encode, /* cvrt HOST to NET if T */
|
||||
arrayElementCount num /* number of values */
|
||||
)
|
||||
{
|
||||
struct dbr_ctrl_int *pSrc = (struct dbr_ctrl_int *) s;
|
||||
@@ -727,10 +729,10 @@ unsigned long num /* number of values */
|
||||
****************************************************************************/
|
||||
|
||||
LOCAL void cvrt_ctrl_long(
|
||||
const void *s, /* source */
|
||||
void *d, /* destination */
|
||||
int encode, /* cvrt HOST to NET if T */
|
||||
unsigned long num /* number of values */
|
||||
const void *s, /* source */
|
||||
void *d, /* destination */
|
||||
int encode, /* cvrt HOST to NET if T */
|
||||
arrayElementCount num /* number of values */
|
||||
)
|
||||
{
|
||||
struct dbr_ctrl_long *pSrc = (struct dbr_ctrl_long*) s;
|
||||
@@ -767,10 +769,10 @@ unsigned long num /* number of values */
|
||||
****************************************************************************/
|
||||
|
||||
LOCAL void cvrt_ctrl_char(
|
||||
const void *s, /* source */
|
||||
void *d, /* destination */
|
||||
int encode, /* cvrt HOST to NET if T */
|
||||
unsigned long num /* number of values */
|
||||
const void *s, /* source */
|
||||
void *d, /* destination */
|
||||
int encode, /* cvrt HOST to NET if T */
|
||||
arrayElementCount num /* number of values */
|
||||
)
|
||||
{
|
||||
struct dbr_ctrl_char *pSrc = (struct dbr_ctrl_char *) s;
|
||||
@@ -805,10 +807,10 @@ unsigned long num /* number of values */
|
||||
****************************************************************************/
|
||||
|
||||
LOCAL void cvrt_ctrl_double(
|
||||
const void *s, /* source */
|
||||
void *d, /* destination */
|
||||
int encode, /* cvrt HOST to NET if T */
|
||||
unsigned long num /* number of values */
|
||||
const void *s, /* source */
|
||||
void *d, /* destination */
|
||||
int encode, /* cvrt HOST to NET if T */
|
||||
arrayElementCount num /* number of values */
|
||||
)
|
||||
{
|
||||
struct dbr_ctrl_double *pSrc = (struct dbr_ctrl_double *) s;
|
||||
@@ -869,10 +871,10 @@ unsigned long num /* number of values */
|
||||
****************************************************************************/
|
||||
|
||||
LOCAL void cvrt_ctrl_float(
|
||||
const void *s, /* source */
|
||||
void *d, /* destination */
|
||||
int encode, /* cvrt HOST to NET if T */
|
||||
unsigned long num /* number of values */
|
||||
const void *s, /* source */
|
||||
void *d, /* destination */
|
||||
int encode, /* cvrt HOST to NET if T */
|
||||
arrayElementCount num /* number of values */
|
||||
)
|
||||
{
|
||||
struct dbr_ctrl_float *pSrc = (struct dbr_ctrl_float *) s;
|
||||
@@ -932,10 +934,10 @@ unsigned long num /* number of values */
|
||||
****************************************************************************/
|
||||
|
||||
LOCAL void cvrt_ctrl_enum(
|
||||
const void *s, /* source */
|
||||
void *d, /* destination */
|
||||
int encode, /* cvrt HOST to NET if T */
|
||||
unsigned long num /* number of values */
|
||||
const void *s, /* source */
|
||||
void *d, /* destination */
|
||||
int encode, /* cvrt HOST to NET if T */
|
||||
arrayElementCount num /* number of values */
|
||||
)
|
||||
{
|
||||
struct dbr_ctrl_enum *pSrc = (struct dbr_ctrl_enum *) s;
|
||||
@@ -968,10 +970,10 @@ unsigned long num /* number of values */
|
||||
****************************************************************************/
|
||||
|
||||
LOCAL void cvrt_sts_char(
|
||||
const void *s, /* source */
|
||||
void *d, /* destination */
|
||||
int encode, /* cvrt HOST to NET if T */
|
||||
unsigned long num /* number of values */
|
||||
const void *s, /* source */
|
||||
void *d, /* destination */
|
||||
int encode, /* cvrt HOST to NET if T */
|
||||
arrayElementCount num /* number of values */
|
||||
)
|
||||
{
|
||||
struct dbr_sts_char *pSrc = (struct dbr_sts_char *) s;
|
||||
@@ -999,10 +1001,10 @@ unsigned long num /* number of values */
|
||||
****************************************************************************/
|
||||
|
||||
LOCAL void cvrt_sts_long(
|
||||
const void *s, /* source */
|
||||
void *d, /* destination */
|
||||
int encode, /* cvrt HOST to NET if T */
|
||||
unsigned long num /* number of values */
|
||||
const void *s, /* source */
|
||||
void *d, /* destination */
|
||||
int encode, /* cvrt HOST to NET if T */
|
||||
arrayElementCount num /* number of values */
|
||||
)
|
||||
{
|
||||
struct dbr_sts_long *pSrc = (struct dbr_sts_long *) s;
|
||||
@@ -1031,10 +1033,10 @@ unsigned long num /* number of values */
|
||||
****************************************************************************/
|
||||
|
||||
LOCAL void cvrt_time_string(
|
||||
const void *s, /* source */
|
||||
void *d, /* destination */
|
||||
int encode, /* cvrt HOST to NET if T */
|
||||
unsigned long num /* number of values */
|
||||
const void *s, /* source */
|
||||
void *d, /* destination */
|
||||
int encode, /* cvrt HOST to NET if T */
|
||||
arrayElementCount num /* number of values */
|
||||
)
|
||||
{
|
||||
struct dbr_time_string *pSrc = (struct dbr_time_string *) s;
|
||||
@@ -1063,10 +1065,10 @@ unsigned long num /* number of values */
|
||||
****************************************************************************/
|
||||
|
||||
LOCAL void cvrt_time_short(
|
||||
const void *s, /* source */
|
||||
void *d, /* destination */
|
||||
int encode, /* cvrt HOST to NET if T */
|
||||
unsigned long num /* number of values */
|
||||
const void *s, /* source */
|
||||
void *d, /* destination */
|
||||
int encode, /* cvrt HOST to NET if T */
|
||||
arrayElementCount num /* number of values */
|
||||
)
|
||||
{
|
||||
struct dbr_time_short *pSrc = (struct dbr_time_short *) s;
|
||||
@@ -1097,10 +1099,10 @@ unsigned long num /* number of values */
|
||||
****************************************************************************/
|
||||
|
||||
LOCAL void cvrt_time_float(
|
||||
const void *s, /* source */
|
||||
void *d, /* destination */
|
||||
int encode, /* cvrt HOST to NET if T */
|
||||
unsigned long num /* number of values */
|
||||
const void *s, /* source */
|
||||
void *d, /* destination */
|
||||
int encode, /* cvrt HOST to NET if T */
|
||||
arrayElementCount num /* number of values */
|
||||
)
|
||||
{
|
||||
struct dbr_time_float *pSrc = (struct dbr_time_float *) s;
|
||||
@@ -1125,10 +1127,10 @@ unsigned long num /* number of values */
|
||||
****************************************************************************/
|
||||
|
||||
LOCAL void cvrt_time_double(
|
||||
const void *s, /* source */
|
||||
void *d, /* destination */
|
||||
int encode, /* cvrt HOST to NET if T */
|
||||
unsigned long num /* number of values */
|
||||
const void *s, /* source */
|
||||
void *d, /* destination */
|
||||
int encode, /* cvrt HOST to NET if T */
|
||||
arrayElementCount num /* number of values */
|
||||
)
|
||||
{
|
||||
struct dbr_time_double *pSrc = (struct dbr_time_double *) s;
|
||||
@@ -1154,10 +1156,10 @@ unsigned long num /* number of values */
|
||||
****************************************************************************/
|
||||
|
||||
LOCAL void cvrt_time_enum(
|
||||
const void *s, /* source */
|
||||
void *d, /* destination */
|
||||
int encode, /* cvrt HOST to NET if T */
|
||||
unsigned long num /* number of values */
|
||||
const void *s, /* source */
|
||||
void *d, /* destination */
|
||||
int encode, /* cvrt HOST to NET if T */
|
||||
arrayElementCount num /* number of values */
|
||||
)
|
||||
{
|
||||
struct dbr_time_enum *pSrc = (struct dbr_time_enum *) s;
|
||||
@@ -1184,10 +1186,10 @@ unsigned long num /* number of values */
|
||||
****************************************************************************/
|
||||
|
||||
LOCAL void cvrt_time_char(
|
||||
const void *s, /* source */
|
||||
void *d, /* destination */
|
||||
int encode, /* cvrt HOST to NET if T */
|
||||
unsigned long num /* number of values */
|
||||
const void *s, /* source */
|
||||
void *d, /* destination */
|
||||
int encode, /* cvrt HOST to NET if T */
|
||||
arrayElementCount num /* number of values */
|
||||
)
|
||||
{
|
||||
struct dbr_time_char *pSrc = (struct dbr_time_char *) s;
|
||||
@@ -1216,10 +1218,10 @@ unsigned long num /* number of values */
|
||||
****************************************************************************/
|
||||
|
||||
LOCAL void cvrt_time_long(
|
||||
const void *s, /* source */
|
||||
void *d, /* destination */
|
||||
int encode, /* cvrt HOST to NET if T */
|
||||
unsigned long num /* number of values */
|
||||
const void *s, /* source */
|
||||
void *d, /* destination */
|
||||
int encode, /* cvrt HOST to NET if T */
|
||||
arrayElementCount num /* number of values */
|
||||
)
|
||||
{
|
||||
struct dbr_time_long *pSrc = (struct dbr_time_long *) s;
|
||||
@@ -1247,15 +1249,15 @@ unsigned long num /* number of values */
|
||||
*
|
||||
*/
|
||||
LOCAL void cvrt_put_ackt(
|
||||
const void *s, /* source */
|
||||
void *d, /* destination */
|
||||
int encode, /* cvrt HOST to NET if T */
|
||||
unsigned long num /* number of values */
|
||||
const void *s, /* source */
|
||||
void *d, /* destination */
|
||||
int encode, /* cvrt HOST to NET if T */
|
||||
arrayElementCount num /* number of values */
|
||||
)
|
||||
{
|
||||
dbr_put_ackt_t *pSrc = (dbr_put_ackt_t *) s;
|
||||
dbr_put_ackt_t *pDest = (dbr_put_ackt_t *) d;
|
||||
unsigned long i;
|
||||
dbr_put_ackt_t *pSrc = (dbr_put_ackt_t *) s;
|
||||
dbr_put_ackt_t *pDest = (dbr_put_ackt_t *) d;
|
||||
arrayElementCount i;
|
||||
|
||||
for(i=0; i<num; i++){
|
||||
*pDest = dbr_ntohs( *pSrc );
|
||||
@@ -1281,10 +1283,10 @@ unsigned long num /* number of values */
|
||||
****************************************************************************/
|
||||
|
||||
LOCAL void cvrt_stsack_string(
|
||||
const void *s, /* source */
|
||||
void *d, /* destination */
|
||||
int encode, /* cvrt HOST to NET if T */
|
||||
unsigned long num /* number of values */
|
||||
const void *s, /* source */
|
||||
void *d, /* destination */
|
||||
int encode, /* cvrt HOST to NET if T */
|
||||
arrayElementCount num /* number of values */
|
||||
)
|
||||
{
|
||||
struct dbr_stsack_string *pSrc = (struct dbr_stsack_string *) s;
|
||||
|
||||
+1
-1
@@ -586,7 +586,7 @@ struct dbr_ctrl_double{
|
||||
};
|
||||
|
||||
#define dbr_size_n(TYPE,COUNT)\
|
||||
((unsigned)((COUNT)==1?dbr_size[TYPE]:dbr_size[TYPE]+((COUNT)-1)*dbr_value_size[TYPE]))
|
||||
((unsigned)((COUNT)<=0?dbr_size[TYPE]:dbr_size[TYPE]+((COUNT)-1)*dbr_value_size[TYPE]))
|
||||
|
||||
/* size for each type - array indexed by the DBR_ type code */
|
||||
epicsShareExtern READONLY unsigned short dbr_size[LAST_BUFFER_TYPE+1];
|
||||
|
||||
@@ -13,3 +13,19 @@ o detect name conflicts at boot time
|
||||
o multi priority connections (quality of service)
|
||||
o reduce protocol overhead
|
||||
o compressed protocol
|
||||
|
||||
|
||||
o If there is a beacon anomaly then this indicates that
|
||||
the server is _not_ available. Perhaps we should only
|
||||
reset the search timer interval when we see a beacon
|
||||
anomaly transition into a sure steady beacon.
|
||||
|
||||
o make certain that a monitor callback canceling itself
|
||||
does not deadlock.
|
||||
|
||||
o the free list library does not now cause exceptions to
|
||||
occur (it uses new ( nothrow )), and therefore we should
|
||||
change the new handlers to be nothrow also if this is
|
||||
the design goal.
|
||||
|
||||
o test the library when an IOC is running low on memory.
|
||||
|
||||
@@ -32,7 +32,7 @@ getCallback::~getCallback ()
|
||||
}
|
||||
|
||||
void getCallback::completion (
|
||||
unsigned type, unsigned long count, const void *pData )
|
||||
unsigned type, arrayElementCount count, const void *pData )
|
||||
{
|
||||
struct event_handler_args args;
|
||||
args.usr = this->pPrivate;
|
||||
@@ -47,7 +47,7 @@ void getCallback::completion (
|
||||
|
||||
void getCallback::exception (
|
||||
int status, const char * /* pContext */,
|
||||
unsigned type, unsigned long count )
|
||||
unsigned type, arrayElementCount count )
|
||||
{
|
||||
struct event_handler_args args;
|
||||
args.usr = this->pPrivate;
|
||||
|
||||
+7
-7
@@ -24,9 +24,9 @@
|
||||
tsFreeList < class getCopy, 1024 > getCopy::freeList;
|
||||
epicsMutex getCopy::freeListMutex;
|
||||
|
||||
getCopy::getCopy ( oldCAC &cacCtxIn, unsigned typeIn,
|
||||
unsigned long countIn, void *pValueIn ) :
|
||||
count ( countIn ), cacCtx ( cacCtxIn ), pValue ( pValueIn ),
|
||||
getCopy::getCopy ( oldCAC &cacCtxIn, oldChannelNotify &chanIn, unsigned typeIn,
|
||||
arrayElementCount countIn, void *pValueIn ) :
|
||||
count ( countIn ), cacCtx ( cacCtxIn ), chan ( chanIn ), pValue ( pValueIn ),
|
||||
readSeq ( cacCtxIn.sequenceNumberOfOutstandingIO () ), type ( typeIn )
|
||||
{
|
||||
cacCtxIn.incrementOutstandingIO ();
|
||||
@@ -37,7 +37,7 @@ getCopy::~getCopy ()
|
||||
}
|
||||
|
||||
void getCopy::completion ( unsigned typeIn,
|
||||
unsigned long countIn, const void *pDataIn )
|
||||
arrayElementCount countIn, const void *pDataIn )
|
||||
{
|
||||
if ( this->type == typeIn ) {
|
||||
memcpy ( this->pValue, pDataIn, dbr_size_n ( typeIn, countIn ) );
|
||||
@@ -52,10 +52,10 @@ void getCopy::completion ( unsigned typeIn,
|
||||
}
|
||||
|
||||
void getCopy::exception (
|
||||
int status, const char *pContext, unsigned typeIn, unsigned long countIn )
|
||||
int status, const char *pContext, unsigned typeIn, arrayElementCount countIn )
|
||||
{
|
||||
this->cacCtx.exception ( status, pContext, typeIn,
|
||||
countIn, __FILE__, __LINE__ );
|
||||
this->cacCtx.exception ( status, pContext,
|
||||
__FILE__, __LINE__, this->chan, this->type, this->count, CA_OP_GET );
|
||||
delete this;
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ public:
|
||||
resTableIndex hash ( unsigned nBitsHashIndex ) const;
|
||||
static unsigned maxIndexBitWidth ();
|
||||
static unsigned minIndexBitWidth ();
|
||||
void name ( char *pBuf, unsigned bufSize ) const;
|
||||
private:
|
||||
const struct sockaddr_in addr;
|
||||
};
|
||||
@@ -60,6 +61,11 @@ inline unsigned inetAddrID::minIndexBitWidth ()
|
||||
return 8u;
|
||||
}
|
||||
|
||||
inline void inetAddrID::name ( char *pBuf, unsigned bufSize ) const
|
||||
{
|
||||
ipAddrToDottedIP ( &this->addr, pBuf, bufSize );
|
||||
}
|
||||
|
||||
#endif // ifdef inetAddrID
|
||||
|
||||
|
||||
|
||||
+1
-13
@@ -22,7 +22,7 @@
|
||||
#define NO_PLACEMENT_DELETE
|
||||
|
||||
#ifdef DEBUG
|
||||
# define debugPrintf(argsInParen) printf argsInParen
|
||||
# define debugPrintf(argsInParen) ::printf argsInParen
|
||||
#else
|
||||
# define debugPrintf(argsInParen)
|
||||
#endif
|
||||
@@ -38,18 +38,6 @@
|
||||
#define MSEC_PER_SEC 1000L
|
||||
#define USEC_PER_SEC 1000000L
|
||||
|
||||
/*
|
||||
* these control the duration and period of name resolution
|
||||
* broadcasts
|
||||
*/
|
||||
#define MAXCONNTRIES 100 /* N conn retries on unchanged net */
|
||||
|
||||
#define INITIALTRIESPERFRAME 1u /* initial UDP frames per search try */
|
||||
#define MAXTRIESPERFRAME 64u /* max UDP frames per search try */
|
||||
|
||||
#define CA_RECAST_DELAY 0.5 /* initial delay to next search (sec) */
|
||||
#define CA_RECAST_PORT_MASK 0xff /* additional random search interval from port */
|
||||
#define CA_RECAST_PERIOD 5.0 /* quiescent search period (sec) */
|
||||
|
||||
#if defined (CLOCKS_PER_SEC)
|
||||
# define CAC_SIGNIFICANT_SELECT_DELAY ( 1.0 / CLOCKS_PER_SEC )
|
||||
|
||||
+21
-11
@@ -81,7 +81,7 @@ nciu::~nciu ()
|
||||
}
|
||||
|
||||
void nciu::connect ( unsigned nativeType,
|
||||
unsigned long nativeCount, unsigned sidIn )
|
||||
unsigned nativeCount, unsigned sidIn )
|
||||
{
|
||||
bool v41Ok;
|
||||
|
||||
@@ -99,6 +99,12 @@ void nciu::connect ( unsigned nativeType,
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! dbf_type_is_valid ( nativeType ) ) {
|
||||
this->cacCtx.printf (
|
||||
"CAC: Ignored conn resp with bad native data type CID=%u SID=%u?\n",
|
||||
this->getId (), sidIn );
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! this->f_connectTimeOutSeen && ! this->f_previousConn ) {
|
||||
if ( this->f_firstConnectDecrementsOutstandingIO ) {
|
||||
@@ -112,7 +118,7 @@ void nciu::connect ( unsigned nativeType,
|
||||
else {
|
||||
v41Ok = false;
|
||||
}
|
||||
this->typeCode = nativeType;
|
||||
this->typeCode = static_cast < unsigned short > ( nativeType );
|
||||
this->count = nativeCount;
|
||||
this->sid = sidIn;
|
||||
this->f_connected = true;
|
||||
@@ -131,6 +137,11 @@ void nciu::connect ( unsigned nativeType,
|
||||
// resubscribe for monitors from this channel
|
||||
this->cacCtx.connectAllIO ( *this );
|
||||
|
||||
static bool once = 0;
|
||||
if ( ! once ) {
|
||||
printf ( "there is a problem here where we are calling through a defunct vf table\n" );
|
||||
once = 1;
|
||||
}
|
||||
this->notify().connectNotify ();
|
||||
|
||||
/*
|
||||
@@ -189,7 +200,7 @@ bool nciu::searchMsg ( unsigned short retrySeqNumber, unsigned &retryNoForThisCh
|
||||
msg.m_cmmd = htons ( CA_PROTO_SEARCH );
|
||||
msg.m_available = this->getId ();
|
||||
msg.m_dataType = htons ( DONTREPLY );
|
||||
msg.m_count = htons ( CA_MINOR_VERSION );
|
||||
msg.m_count = htons ( CA_MINOR_PROTOCOL_REVISION );
|
||||
msg.m_cid = this->getId ();
|
||||
|
||||
success = this->piiu->pushDatagramMsg ( msg,
|
||||
@@ -199,7 +210,7 @@ bool nciu::searchMsg ( unsigned short retrySeqNumber, unsigned &retryNoForThisCh
|
||||
// increment the number of times we have tried
|
||||
// to find this channel
|
||||
//
|
||||
if ( this->retry < MAXCONNTRIES ) {
|
||||
if ( this->retry < UINT_MAX ) {
|
||||
this->retry++;
|
||||
}
|
||||
this->retrySeqNo = retrySeqNumber;
|
||||
@@ -226,7 +237,7 @@ void nciu::createChannelRequest ()
|
||||
this->f_claimSent = true;
|
||||
}
|
||||
|
||||
cacChannel::ioStatus nciu::read ( unsigned type, unsigned long countIn,
|
||||
cacChannel::ioStatus nciu::read ( unsigned type, arrayElementCount countIn,
|
||||
cacReadNotify ¬ify, ioid *pId )
|
||||
{
|
||||
//
|
||||
@@ -270,7 +281,7 @@ void nciu::stringVerify ( const char *pStr, const unsigned count )
|
||||
}
|
||||
|
||||
void nciu::write ( unsigned type,
|
||||
unsigned long countIn, const void *pValue )
|
||||
arrayElementCount countIn, const void *pValue )
|
||||
{
|
||||
if ( ! this->accessRightState.writePermit() ) {
|
||||
throw noWriteAccess();
|
||||
@@ -287,7 +298,7 @@ void nciu::write ( unsigned type,
|
||||
this->cacCtx.writeRequest ( *this, type, countIn, pValue );
|
||||
}
|
||||
|
||||
cacChannel::ioStatus nciu::write ( unsigned type, unsigned long countIn,
|
||||
cacChannel::ioStatus nciu::write ( unsigned type, arrayElementCount countIn,
|
||||
const void *pValue, cacWriteNotify ¬ify, ioid *pId )
|
||||
{
|
||||
if ( ! this->accessRightState.writePermit() ) {
|
||||
@@ -309,7 +320,7 @@ cacChannel::ioStatus nciu::write ( unsigned type, unsigned long countIn,
|
||||
return cacChannel::iosAsynch;
|
||||
}
|
||||
|
||||
void nciu::subscribe ( unsigned type, unsigned long nElem,
|
||||
void nciu::subscribe ( unsigned type, arrayElementCount nElem,
|
||||
unsigned mask, cacStateNotify ¬ify, ioid *pId )
|
||||
{
|
||||
if ( INVALID_DB_REQ(type) ) {
|
||||
@@ -380,10 +391,10 @@ short nciu::nativeType () const
|
||||
return type;
|
||||
}
|
||||
|
||||
unsigned long nciu::nativeElementCount () const
|
||||
arrayElementCount nciu::nativeElementCount () const
|
||||
{
|
||||
epicsAutoMutex locker ( this->cacCtx.mutexRef() );
|
||||
unsigned long countOut;
|
||||
arrayElementCount countOut;
|
||||
if ( this->f_connected ) {
|
||||
countOut = this->count;
|
||||
}
|
||||
@@ -471,4 +482,3 @@ void nciu::show ( unsigned level ) const
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+19
-11
@@ -23,6 +23,7 @@
|
||||
#include "tsFreeList.h"
|
||||
#include "epicsMutex.h"
|
||||
|
||||
#define CA_MINOR_PROTOCOL_REVISION 9
|
||||
#include "caProto.h"
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
@@ -44,7 +45,7 @@ public:
|
||||
nciu ( cac &, netiiu &,
|
||||
cacChannelNotify &, const char *pNameIn );
|
||||
void connect ( unsigned nativeType,
|
||||
unsigned long nativeCount, unsigned sid );
|
||||
unsigned nativeCount, unsigned sid );
|
||||
void connect ();
|
||||
void disconnect ( netiiu &newiiu );
|
||||
bool searchMsg ( unsigned short retrySeqNumber,
|
||||
@@ -61,15 +62,16 @@ public:
|
||||
netiiu * getPIIU ();
|
||||
cac & getClient ();
|
||||
void searchReplySetUp ( netiiu &iiu, unsigned sidIn,
|
||||
unsigned typeIn, unsigned long countIn );
|
||||
ca_uint16_t typeIn, arrayElementCount countIn );
|
||||
void show ( unsigned level ) const;
|
||||
void connectTimeoutNotify ();
|
||||
const char *pName () const;
|
||||
unsigned nameLen () const;
|
||||
const char * pHostName () const; // deprecated - please do not use
|
||||
unsigned long nativeElementCount () const;
|
||||
arrayElementCount nativeElementCount () const;
|
||||
bool connected () const;
|
||||
bool previouslyConnected () const;
|
||||
void writeException ( int status, const char *pContext, unsigned type, arrayElementCount count );
|
||||
protected:
|
||||
~nciu (); // force pool allocation
|
||||
private:
|
||||
@@ -80,22 +82,22 @@ private:
|
||||
netiiu *piiu;
|
||||
ca_uint32_t sid; // server id
|
||||
unsigned retry; // search retry number
|
||||
unsigned short retrySeqNo; // search retry seq number
|
||||
unsigned short nameLength; // channel name length
|
||||
unsigned short typeCode;
|
||||
ca_uint16_t retrySeqNo; // search retry seq number
|
||||
ca_uint16_t nameLength; // channel name length
|
||||
ca_uint16_t typeCode;
|
||||
unsigned f_connected:1;
|
||||
unsigned f_previousConn:1; // T if connected in the past
|
||||
unsigned f_claimSent:1;
|
||||
unsigned f_firstConnectDecrementsOutstandingIO:1;
|
||||
unsigned f_connectTimeOutSeen:1;
|
||||
void initiateConnect ();
|
||||
ioStatus read ( unsigned type, unsigned long count,
|
||||
ioStatus read ( unsigned type, arrayElementCount count,
|
||||
cacReadNotify &, ioid * );
|
||||
void write ( unsigned type, unsigned long count,
|
||||
void write ( unsigned type, arrayElementCount count,
|
||||
const void *pValue );
|
||||
ioStatus write ( unsigned type, unsigned long count,
|
||||
ioStatus write ( unsigned type, arrayElementCount count,
|
||||
const void *pValue, cacWriteNotify &, ioid * );
|
||||
void subscribe ( unsigned type, unsigned long nElem,
|
||||
void subscribe ( unsigned type, arrayElementCount nElem,
|
||||
unsigned mask, cacStateNotify ¬ify, ioid * );
|
||||
void ioCancel ( const ioid & );
|
||||
void ioShow ( const ioid &, unsigned level ) const;
|
||||
@@ -161,7 +163,7 @@ inline void nciu::connect ()
|
||||
}
|
||||
|
||||
inline void nciu::searchReplySetUp ( netiiu &iiu, unsigned sidIn,
|
||||
unsigned typeIn, unsigned long countIn )
|
||||
ca_uint16_t typeIn, arrayElementCount countIn )
|
||||
{
|
||||
this->piiu = &iiu;
|
||||
this->typeCode = typeIn;
|
||||
@@ -194,4 +196,10 @@ inline void nciu::connectTimeoutNotify ()
|
||||
this->f_connectTimeOutSeen = true;
|
||||
}
|
||||
|
||||
inline void nciu::writeException ( int status,
|
||||
const char *pContext, unsigned type, arrayElementCount count )
|
||||
{
|
||||
this->notify().writeException ( status, pContext, type, count );
|
||||
}
|
||||
|
||||
#endif // ifdef nciuh
|
||||
|
||||
+25
-21
@@ -27,11 +27,13 @@ public:
|
||||
virtual class netSubscription * isSubscription ();
|
||||
virtual void destroy ( class cacRecycle & ) = 0; // only called by cac
|
||||
virtual void completion () = 0;
|
||||
virtual void exception ( int status, const char *pContext ) = 0;
|
||||
virtual void completion ( unsigned type,
|
||||
unsigned long count, const void *pData ) = 0;
|
||||
virtual void exception ( int status,
|
||||
const char *pContext, unsigned type, unsigned long count ) = 0;
|
||||
const char *pContext ) = 0;
|
||||
virtual void exception ( int status,
|
||||
const char *pContext, unsigned type,
|
||||
arrayElementCount count ) = 0;
|
||||
virtual void completion ( unsigned type,
|
||||
arrayElementCount count, const void *pData ) = 0;
|
||||
void show ( unsigned level ) const;
|
||||
ca_uint32_t getID () const;
|
||||
nciu & channel () const;
|
||||
@@ -48,27 +50,29 @@ class netSubscription : public baseNMIU {
|
||||
public:
|
||||
static netSubscription * factory (
|
||||
tsFreeList < class netSubscription, 1024 > &,
|
||||
nciu &chan, unsigned type, unsigned long count,
|
||||
nciu &chan, unsigned type, arrayElementCount count,
|
||||
unsigned mask, cacStateNotify ¬ify );
|
||||
void show ( unsigned level ) const;
|
||||
unsigned long getCount () const;
|
||||
arrayElementCount getCount () const;
|
||||
unsigned getType () const;
|
||||
unsigned getMask () const;
|
||||
void destroy ( class cacRecycle & );
|
||||
void completion ();
|
||||
void exception ( int status, const char *pContext );
|
||||
void completion ( unsigned type,
|
||||
unsigned long count, const void *pData );
|
||||
void exception ( int status,
|
||||
const char *pContext, unsigned type, unsigned long count );
|
||||
const char *pContext );
|
||||
void completion ( unsigned type,
|
||||
arrayElementCount count, const void *pData );
|
||||
void exception ( int status,
|
||||
const char *pContext, unsigned type,
|
||||
arrayElementCount count );
|
||||
protected:
|
||||
~netSubscription ();
|
||||
private:
|
||||
const unsigned long count;
|
||||
const arrayElementCount count;
|
||||
cacStateNotify ¬ify;
|
||||
const unsigned type;
|
||||
const unsigned mask;
|
||||
netSubscription ( nciu &chan, unsigned type, unsigned long count,
|
||||
netSubscription ( nciu &chan, unsigned type, arrayElementCount count,
|
||||
unsigned mask, cacStateNotify ¬ify );
|
||||
class netSubscription * isSubscription ();
|
||||
void * operator new ( size_t,
|
||||
@@ -89,9 +93,9 @@ public:
|
||||
void completion ();
|
||||
void exception ( int status, const char *pContext );
|
||||
void completion ( unsigned type,
|
||||
unsigned long count, const void *pData );
|
||||
void exception ( int status,
|
||||
const char *pContext, unsigned type, unsigned long count );
|
||||
arrayElementCount count, const void *pData );
|
||||
void exception ( int status, const char *pContext,
|
||||
unsigned type, arrayElementCount count );
|
||||
protected:
|
||||
~netReadNotifyIO ();
|
||||
private:
|
||||
@@ -115,9 +119,9 @@ public:
|
||||
void completion ();
|
||||
void exception ( int status, const char *pContext );
|
||||
void completion ( unsigned type,
|
||||
unsigned long count, const void *pData );
|
||||
void exception ( int status,
|
||||
const char *pContext, unsigned type, unsigned long count );
|
||||
arrayElementCount count, const void *pData );
|
||||
void exception ( int status, const char *pContext,
|
||||
unsigned type, arrayElementCount count );
|
||||
protected:
|
||||
~netWriteNotifyIO ();
|
||||
private:
|
||||
@@ -143,7 +147,7 @@ inline class nciu & baseNMIU::channel () const
|
||||
|
||||
inline netSubscription * netSubscription::factory (
|
||||
tsFreeList < class netSubscription, 1024 > &freeList,
|
||||
nciu &chan, unsigned type, unsigned long count,
|
||||
nciu &chan, unsigned type, arrayElementCount count,
|
||||
unsigned mask, cacStateNotify ¬ify )
|
||||
{
|
||||
return new ( freeList ) netSubscription ( chan, type,
|
||||
@@ -169,9 +173,9 @@ inline void netSubscription::operator delete ( void *pCadaver, size_t size,
|
||||
}
|
||||
#endif
|
||||
|
||||
inline unsigned long netSubscription::getCount () const
|
||||
inline arrayElementCount netSubscription::getCount () const
|
||||
{
|
||||
unsigned long nativeCount = this->chan.nativeElementCount ();
|
||||
arrayElementCount nativeCount = this->chan.nativeElementCount ();
|
||||
if ( this->count == 0u || this->count > nativeCount ) {
|
||||
return nativeCount;
|
||||
}
|
||||
|
||||
@@ -48,20 +48,20 @@ void netReadNotifyIO::completion ()
|
||||
|
||||
void netReadNotifyIO::exception ( int status, const char *pContext )
|
||||
{
|
||||
this->notify.exception ( status, pContext, UINT_MAX, 0 );
|
||||
this->notify.exception ( status, pContext, UINT_MAX, 0u );
|
||||
}
|
||||
|
||||
void netReadNotifyIO::completion ( unsigned type,
|
||||
unsigned long count, const void *pData )
|
||||
{
|
||||
this->notify.completion ( type, count, pData );
|
||||
}
|
||||
|
||||
void netReadNotifyIO::exception ( int status,
|
||||
const char *pContext, unsigned type, unsigned long count )
|
||||
void netReadNotifyIO::exception ( int status, const char *pContext,
|
||||
unsigned type, arrayElementCount count )
|
||||
{
|
||||
this->notify.exception ( status, pContext, type, count );
|
||||
}
|
||||
|
||||
void netReadNotifyIO::completion ( unsigned type,
|
||||
arrayElementCount count, const void *pData )
|
||||
{
|
||||
this->notify.completion ( type, count, pData );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -22,11 +22,17 @@
|
||||
#undef epicsExportSharedSymbols
|
||||
|
||||
netSubscription::netSubscription ( nciu &chan,
|
||||
unsigned typeIn, unsigned long countIn,
|
||||
unsigned typeIn, arrayElementCount countIn,
|
||||
unsigned maskIn, cacStateNotify ¬ifyIn ) :
|
||||
baseNMIU ( chan ), count ( countIn ),
|
||||
notify ( notifyIn ), type ( typeIn ), mask ( maskIn )
|
||||
{
|
||||
if ( ! dbr_type_is_valid ( typeIn ) ) {
|
||||
throw cacChannel::badType ();
|
||||
}
|
||||
if ( this->mask == 0u ) {
|
||||
throw cacChannel::badEventSelection ();
|
||||
}
|
||||
}
|
||||
|
||||
netSubscription::~netSubscription ()
|
||||
@@ -65,16 +71,17 @@ void netSubscription::exception ( int status, const char *pContext )
|
||||
this->notify.exception ( status, pContext, UINT_MAX, 0 );
|
||||
}
|
||||
|
||||
void netSubscription::exception ( int status, const char *pContext,
|
||||
unsigned type, arrayElementCount count )
|
||||
{
|
||||
this->notify.exception ( status, pContext, type, count );
|
||||
}
|
||||
|
||||
void netSubscription::completion ( unsigned typeIn,
|
||||
unsigned long countIn, const void *pDataIn )
|
||||
arrayElementCount countIn, const void *pDataIn )
|
||||
{
|
||||
this->notify.current ( typeIn, countIn, pDataIn );
|
||||
}
|
||||
|
||||
void netSubscription::exception ( int status,
|
||||
const char *pContext, unsigned typeIn, unsigned long countIn )
|
||||
{
|
||||
this->notify.exception ( status, pContext, typeIn, countIn );
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -48,21 +48,22 @@ void netWriteNotifyIO::completion ()
|
||||
|
||||
void netWriteNotifyIO::exception ( int status, const char *pContext )
|
||||
{
|
||||
this->notify.exception ( status, pContext );
|
||||
this->notify.exception ( status, pContext, UINT_MAX, 0u );
|
||||
}
|
||||
|
||||
void netWriteNotifyIO::exception ( int status, const char *pContext,
|
||||
unsigned type, arrayElementCount count )
|
||||
{
|
||||
this->notify.exception ( status, pContext, type, count );
|
||||
}
|
||||
|
||||
|
||||
void netWriteNotifyIO::completion ( unsigned /* type */,
|
||||
unsigned long /* count */, const void * /* pData */ )
|
||||
arrayElementCount /* count */, const void * /* pData */ )
|
||||
{
|
||||
this->chan.getClient().printf ( "Write response with data ?\n" );
|
||||
}
|
||||
|
||||
void netWriteNotifyIO::exception ( int status,
|
||||
const char *pContext, unsigned /* type */, unsigned long /* count */ )
|
||||
{
|
||||
this->notify.exception ( status, pContext );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -67,7 +67,7 @@ extern "C" {
|
||||
* net format: big endian and IEEE float
|
||||
*/
|
||||
|
||||
typedef void CACVRTFUNC (const void *pSrc, void *pDest, int hton, unsigned long count);
|
||||
typedef void CACVRTFUNC (const void *pSrc, void *pDest, int hton, arrayElementCount count);
|
||||
|
||||
#ifdef CONVERSION_REQUIRED
|
||||
/* cvrt is (array of) (pointer to) (function returning) int */
|
||||
|
||||
+49
-34
@@ -44,24 +44,24 @@ public:
|
||||
void show ( unsigned level ) const;
|
||||
void initiateConnect ();
|
||||
void read (
|
||||
unsigned type, unsigned long count,
|
||||
unsigned type, arrayElementCount count,
|
||||
cacReadNotify ¬ify, cacChannel::ioid *pId = 0 );
|
||||
void read (
|
||||
unsigned type, unsigned long count,
|
||||
unsigned type, arrayElementCount count,
|
||||
void *pValue );
|
||||
void write (
|
||||
unsigned type, unsigned long count,
|
||||
unsigned type, arrayElementCount count,
|
||||
const void *pValue );
|
||||
void write (
|
||||
unsigned type, unsigned long count, const void *pValue,
|
||||
unsigned type, arrayElementCount count, const void *pValue,
|
||||
cacWriteNotify &, cacChannel::ioid *pId = 0 );
|
||||
void subscribe (
|
||||
unsigned type, unsigned long count, unsigned mask,
|
||||
unsigned type, arrayElementCount count, unsigned mask,
|
||||
cacStateNotify &, cacChannel::ioid & );
|
||||
void ioCancel ( const cacChannel::ioid & );
|
||||
void ioShow ( const cacChannel::ioid &, unsigned level ) const;
|
||||
short nativeType () const;
|
||||
unsigned long nativeElementCount () const;
|
||||
arrayElementCount nativeElementCount () const;
|
||||
caAccessRights accessRights () const; // defaults to unrestricted access
|
||||
unsigned searchAttempts () const; // defaults to zero
|
||||
double beaconPeriod () const; // defaults to negative DBL_MAX
|
||||
@@ -81,6 +81,10 @@ private:
|
||||
void disconnectNotify ();
|
||||
void accessRightsNotify ( const caAccessRights & );
|
||||
void exception ( int status, const char *pContext );
|
||||
void readException ( int status, const char *pContext,
|
||||
unsigned type, arrayElementCount count, void *pValue );
|
||||
void writeException ( int status, const char *pContext,
|
||||
unsigned type, arrayElementCount count );
|
||||
bool includeFirstConnectInCountOfOutstandingIO () const;
|
||||
static tsFreeList < struct oldChannelNotify, 1024 > freeList;
|
||||
static epicsMutex freeListMutex;
|
||||
@@ -88,8 +92,8 @@ private:
|
||||
|
||||
class getCopy : public cacReadNotify {
|
||||
public:
|
||||
getCopy ( oldCAC &cacCtx, unsigned type,
|
||||
unsigned long count, void *pValue );
|
||||
getCopy ( oldCAC &cacCtx, oldChannelNotify &, unsigned type,
|
||||
arrayElementCount count, void *pValue );
|
||||
void destroy ();
|
||||
void show ( unsigned level ) const;
|
||||
void * operator new ( size_t size );
|
||||
@@ -97,15 +101,16 @@ public:
|
||||
protected:
|
||||
~getCopy (); // allocate only out of pool
|
||||
private:
|
||||
unsigned long count;
|
||||
arrayElementCount count;
|
||||
oldCAC &cacCtx;
|
||||
oldChannelNotify &chan;
|
||||
void *pValue;
|
||||
unsigned readSeq;
|
||||
unsigned type;
|
||||
void completion (
|
||||
unsigned type, unsigned long count, const void *pData);
|
||||
void exception (
|
||||
int status, const char *pContext, unsigned type, unsigned long count );
|
||||
unsigned type, arrayElementCount count, const void *pData);
|
||||
void exception ( int status,
|
||||
const char *pContext, unsigned type, arrayElementCount count );
|
||||
static tsFreeList < class getCopy, 1024 > freeList;
|
||||
static epicsMutex freeListMutex;
|
||||
};
|
||||
@@ -124,9 +129,9 @@ private:
|
||||
caEventCallBackFunc *pFunc;
|
||||
void *pPrivate;
|
||||
void completion (
|
||||
unsigned type, unsigned long count, const void *pData);
|
||||
void exception (
|
||||
int status, const char *pContext, unsigned type, unsigned long count );
|
||||
unsigned type, arrayElementCount count, const void *pData);
|
||||
void exception ( int status,
|
||||
const char *pContext, unsigned type, arrayElementCount count );
|
||||
static tsFreeList < class getCallback, 1024 > freeList;
|
||||
static epicsMutex freeListMutex;
|
||||
};
|
||||
@@ -145,8 +150,8 @@ private:
|
||||
caEventCallBackFunc *pFunc;
|
||||
void *pPrivate;
|
||||
void completion ();
|
||||
void exception (
|
||||
int status, const char *pContext );
|
||||
void exception ( int status, const char *pContext,
|
||||
unsigned type, arrayElementCount count );
|
||||
static tsFreeList < class putCallback, 1024 > freeList;
|
||||
static epicsMutex freeListMutex;
|
||||
};
|
||||
@@ -155,7 +160,7 @@ struct oldSubscription : public cacStateNotify {
|
||||
public:
|
||||
oldSubscription (
|
||||
oldChannelNotify &,
|
||||
unsigned type, unsigned long nElem, unsigned mask,
|
||||
unsigned type, arrayElementCount nElem, unsigned mask,
|
||||
caEventCallBackFunc *pFunc, void *pPrivate );
|
||||
bool ioAttachOK ();
|
||||
void destroy ();
|
||||
@@ -171,9 +176,9 @@ private:
|
||||
void *pPrivate;
|
||||
bool subscribed;
|
||||
void current (
|
||||
unsigned type, unsigned long count, const void *pData );
|
||||
void exception (
|
||||
int status, const char *pContext, unsigned type, unsigned long count );
|
||||
unsigned type, arrayElementCount count, const void *pData );
|
||||
void exception ( int status,
|
||||
const char *pContext, unsigned type, arrayElementCount count );
|
||||
static tsFreeList < struct oldSubscription, 1024 > freeList;
|
||||
static epicsMutex freeListMutex;
|
||||
};
|
||||
@@ -197,22 +202,24 @@ public:
|
||||
unsigned sequenceNumberOfOutstandingIO () const;
|
||||
void incrementOutstandingIO ();
|
||||
void decrementOutstandingIO ( unsigned sequenceNo );
|
||||
void exception ( int status, const char *pContext,
|
||||
void exception ( int status, const char *pContext,
|
||||
const char *pFileName, unsigned lineNo );
|
||||
void exception ( int status, const char *pContext,
|
||||
unsigned type, unsigned long count,
|
||||
const char *pFileName, unsigned lineNo );
|
||||
// perhaps these should be eliminated in deference to the exception mechanism
|
||||
int printf ( const char *pformat, ... );
|
||||
int vPrintf ( const char *pformat, va_list args );
|
||||
const char *pFileName, unsigned lineNo, oldChannelNotify &chan,
|
||||
unsigned type, arrayElementCount count, unsigned op );
|
||||
CASG * lookupCASG ( unsigned id );
|
||||
void installCASG ( CASG & );
|
||||
void uninstallCASG ( CASG & );
|
||||
void enableCallbackPreemption ();
|
||||
void disableCallbackPreemption ();
|
||||
// perhaps these should be eliminated in deference to the exception mechanism
|
||||
int printf ( const char *pformat, ... ) const;
|
||||
int vPrintf ( const char *pformat, va_list args ) const;
|
||||
void vSignal ( int ca_status, const char *pfilenm,
|
||||
int lineno, const char *pFormat, va_list args );
|
||||
private:
|
||||
cac & clientCtx;
|
||||
mutable epicsMutex mutex;
|
||||
cac & clientCtx;
|
||||
caExceptionHandler *ca_exception_func;
|
||||
void *ca_exception_arg;
|
||||
caPrintfFunc *pVPrintfFunc;
|
||||
@@ -221,6 +228,7 @@ private:
|
||||
// this should probably be phased out (its not OS independent)
|
||||
void fdWasCreated ( int fd );
|
||||
void fdWasDestroyed ( int fd );
|
||||
void attachToClientCtx ();
|
||||
};
|
||||
|
||||
int fetchClientContext ( oldCAC **ppcac );
|
||||
@@ -250,26 +258,26 @@ inline void oldChannelNotify::initiateConnect ()
|
||||
this->io.initiateConnect ();
|
||||
}
|
||||
|
||||
inline void oldChannelNotify::read ( unsigned type, unsigned long count,
|
||||
inline void oldChannelNotify::read ( unsigned type, arrayElementCount count,
|
||||
cacReadNotify ¬ify, cacChannel::ioid *pId )
|
||||
{
|
||||
this->io.read ( type, count, notify, pId );
|
||||
}
|
||||
|
||||
inline void oldChannelNotify::write ( unsigned type,
|
||||
unsigned long count, const void *pValue )
|
||||
arrayElementCount count, const void *pValue )
|
||||
{
|
||||
this->io.write ( type, count, pValue );
|
||||
}
|
||||
|
||||
inline void oldChannelNotify::write ( unsigned type, unsigned long count,
|
||||
inline void oldChannelNotify::write ( unsigned type, arrayElementCount count,
|
||||
const void *pValue, cacWriteNotify ¬ify, cacChannel::ioid *pId )
|
||||
{
|
||||
this->io.write ( type, count, pValue, notify, pId );
|
||||
}
|
||||
|
||||
inline void oldChannelNotify::subscribe ( unsigned type,
|
||||
unsigned long count, unsigned mask, cacStateNotify ¬ify,
|
||||
arrayElementCount count, unsigned mask, cacStateNotify ¬ify,
|
||||
cacChannel::ioid &idOut)
|
||||
{
|
||||
this->io.subscribe ( type, count, mask, notify, &idOut );
|
||||
@@ -290,7 +298,7 @@ inline short oldChannelNotify::nativeType () const
|
||||
return this->io.nativeType ();
|
||||
}
|
||||
|
||||
inline unsigned long oldChannelNotify::nativeElementCount () const
|
||||
inline arrayElementCount oldChannelNotify::nativeElementCount () const
|
||||
{
|
||||
return this->io.nativeElementCount ();
|
||||
}
|
||||
@@ -337,7 +345,7 @@ inline const char * oldChannelNotify::pHostName () const
|
||||
|
||||
inline oldSubscription::oldSubscription (
|
||||
oldChannelNotify &chanIn,
|
||||
unsigned type, unsigned long nElem, unsigned mask,
|
||||
unsigned type, arrayElementCount nElem, unsigned mask,
|
||||
caEventCallBackFunc *pFuncIn, void *pPrivateIn ) :
|
||||
chan ( chanIn ), id ( 0 ), pFunc ( pFuncIn ),
|
||||
pPrivate ( pPrivateIn ), subscribed ( false )
|
||||
@@ -497,4 +505,11 @@ inline void oldCAC::disableCallbackPreemption ()
|
||||
this->clientCtx.disableCallbackPreemption ();
|
||||
}
|
||||
|
||||
inline void oldCAC::vSignal ( int ca_status, const char *pfilenm,
|
||||
int lineno, const char *pFormat, va_list args )
|
||||
{
|
||||
this->clientCtx.vSignal ( ca_status, pfilenm,
|
||||
lineno, pFormat, args );
|
||||
}
|
||||
|
||||
#endif // ifndef oldAccessh
|
||||
|
||||
+70
-36
@@ -14,13 +14,15 @@
|
||||
* 505 665 1831
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "iocinf.h"
|
||||
|
||||
#include "oldAccess.h"
|
||||
|
||||
oldCAC::oldCAC ( bool enablePreemptiveCallback ) :
|
||||
clientCtx ( * new cac ( *this, enablePreemptiveCallback ) ),
|
||||
ca_exception_func ( ca_default_exception_handler ), ca_exception_arg ( 0 ),
|
||||
ca_exception_func ( 0 ), ca_exception_arg ( 0 ),
|
||||
pVPrintfFunc ( errlogVprintf ), fdRegFunc ( 0 ), fdRegArg ( 0 )
|
||||
{
|
||||
if ( ! & this->clientCtx ) {
|
||||
@@ -36,14 +38,8 @@ oldCAC::~oldCAC ()
|
||||
void oldCAC::changeExceptionEvent ( caExceptionHandler *pfunc, void *arg )
|
||||
{
|
||||
epicsAutoMutex autoMutex ( this->mutex );
|
||||
if ( pfunc ) {
|
||||
this->ca_exception_func = pfunc;
|
||||
this->ca_exception_arg = arg;
|
||||
}
|
||||
else {
|
||||
this->ca_exception_func = ca_default_exception_handler;
|
||||
this->ca_exception_arg = NULL;
|
||||
}
|
||||
this->ca_exception_func = pfunc;
|
||||
this->ca_exception_arg = arg;
|
||||
// should block here until releated callback in progress completes
|
||||
}
|
||||
|
||||
@@ -67,8 +63,21 @@ void oldCAC::registerForFileDescriptorCallBack ( CAFDHANDLER *pFunc, void *pArg
|
||||
// should block here until releated callback in progress completes
|
||||
}
|
||||
|
||||
int oldCAC::printf ( const char *pformat, ... ) const
|
||||
{
|
||||
va_list theArgs;
|
||||
int status;
|
||||
|
||||
int oldCAC::vPrintf ( const char *pformat, va_list args )
|
||||
va_start ( theArgs, pformat );
|
||||
|
||||
status = this->oldCAC::vPrintf ( pformat, theArgs );
|
||||
|
||||
va_end ( theArgs );
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
int oldCAC::vPrintf ( const char *pformat, va_list args ) const
|
||||
{
|
||||
caPrintfFunc *pFunc;
|
||||
{
|
||||
@@ -79,18 +88,12 @@ int oldCAC::vPrintf ( const char *pformat, va_list args )
|
||||
return ( *pFunc ) ( pformat, args );
|
||||
}
|
||||
else {
|
||||
return vfprintf ( stderr, pformat, args );
|
||||
return ::vfprintf ( stderr, pformat, args );
|
||||
}
|
||||
}
|
||||
|
||||
void oldCAC::exception ( int stat, const char *pCtx, const char *pFile, unsigned lineNo )
|
||||
{
|
||||
this->exception ( stat, pCtx, UINT_MAX, 0, pFile, lineNo );
|
||||
}
|
||||
|
||||
void oldCAC::exception ( int stat, const char *ctx,
|
||||
unsigned type, unsigned long count,
|
||||
const char *pFile, unsigned lineNo )
|
||||
void oldCAC::exception ( int stat, const char *pCtx,
|
||||
const char *pFile, unsigned lineNo )
|
||||
{
|
||||
struct exception_handler_args args;
|
||||
caExceptionHandler *pFunc;
|
||||
@@ -104,17 +107,54 @@ void oldCAC::exception ( int stat, const char *ctx,
|
||||
// NOOP if they disable exceptions
|
||||
if ( pFunc ) {
|
||||
args.chid = NULL;
|
||||
args.type = type;
|
||||
args.count = count;
|
||||
args.type = TYPENOTCONN;
|
||||
args.count = 0;
|
||||
args.addr = NULL;
|
||||
args.stat = stat;
|
||||
args.op = CA_OP_OTHER;
|
||||
args.ctx = ctx;
|
||||
args.ctx = pCtx;
|
||||
args.pFile = pFile;
|
||||
args.lineNo = lineNo;
|
||||
args.usr = pArg;
|
||||
( *pFunc ) ( args );
|
||||
}
|
||||
else {
|
||||
this->clientCtx.signal ( stat, pFile, lineNo, pCtx );
|
||||
}
|
||||
}
|
||||
|
||||
void oldCAC::exception ( int status, const char *pContext,
|
||||
const char *pFileName, unsigned lineNo, oldChannelNotify &chan,
|
||||
unsigned type, arrayElementCount count, unsigned op )
|
||||
{
|
||||
struct exception_handler_args args;
|
||||
caExceptionHandler *pFunc;
|
||||
void *pArg;
|
||||
{
|
||||
epicsAutoMutex autoMutex ( this->mutex );
|
||||
pFunc = this->ca_exception_func;
|
||||
pArg = this->ca_exception_arg;
|
||||
}
|
||||
|
||||
// NOOP if they disable exceptions
|
||||
if ( pFunc ) {
|
||||
args.chid = &chan;
|
||||
args.type = type;
|
||||
args.count = count;
|
||||
args.addr = NULL;
|
||||
args.stat = status;
|
||||
args.op = op;
|
||||
args.ctx = pContext;
|
||||
args.pFile = pFileName;
|
||||
args.lineNo = lineNo;
|
||||
args.usr = pArg;
|
||||
( *pFunc ) ( args );
|
||||
}
|
||||
else {
|
||||
this->clientCtx.signal ( status, pFileName, lineNo,
|
||||
"op=%u, channel=%s, type=%s, count=lu, ctx=\"%s\"",
|
||||
op, ca_name ( &chan ), dbr_type_to_text ( type ), count, pContext );
|
||||
}
|
||||
}
|
||||
|
||||
void oldCAC::fdWasCreated ( int fd )
|
||||
@@ -145,20 +185,6 @@ void oldCAC::fdWasDestroyed ( int fd )
|
||||
}
|
||||
}
|
||||
|
||||
int oldCAC::printf ( const char *pformat, ... )
|
||||
{
|
||||
va_list theArgs;
|
||||
int status;
|
||||
|
||||
va_start ( theArgs, pformat );
|
||||
|
||||
status = this->vPrintf ( pformat, theArgs );
|
||||
|
||||
va_end ( theArgs );
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
void oldCAC::show ( unsigned level ) const
|
||||
{
|
||||
::printf ( "oldCAC at %p\n",
|
||||
@@ -179,3 +205,11 @@ void oldCAC::show ( unsigned level ) const
|
||||
}
|
||||
}
|
||||
|
||||
void oldCAC::attachToClientCtx ()
|
||||
{
|
||||
int status = ca_attach_context ( this );
|
||||
SEVCHK ( status, "error in virtual attach to client context" );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -113,6 +113,20 @@ void oldChannelNotify::exception ( int status, const char *pContext )
|
||||
ca_signal ( status, pContext );
|
||||
}
|
||||
|
||||
void oldChannelNotify::readException ( int status, const char *pContext,
|
||||
unsigned type, arrayElementCount count, void *pValue )
|
||||
{
|
||||
ca_signal_formated ( status, 0, 0u, "ctx=%s type=%s count=%u ptr=%p",
|
||||
pContext, dbr_type_to_text ( type ), count, pValue );
|
||||
}
|
||||
|
||||
void oldChannelNotify::writeException ( int status, const char *pContext,
|
||||
unsigned type, arrayElementCount count )
|
||||
{
|
||||
ca_signal_formated ( status, 0, 0u, "ctx=%s type=%s count=%u",
|
||||
pContext, dbr_type_to_text ( type ), count );
|
||||
}
|
||||
|
||||
bool oldChannelNotify::includeFirstConnectInCountOfOutstandingIO () const
|
||||
{
|
||||
return ( this->pConnCallBack == cacNoopConnHandler );
|
||||
|
||||
@@ -22,7 +22,7 @@ oldSubscription::~oldSubscription ()
|
||||
}
|
||||
|
||||
void oldSubscription::current (
|
||||
unsigned type, unsigned long count, const void *pData)
|
||||
unsigned type, arrayElementCount count, const void *pData)
|
||||
{
|
||||
struct event_handler_args args;
|
||||
|
||||
@@ -37,7 +37,7 @@ void oldSubscription::current (
|
||||
|
||||
void oldSubscription::exception (
|
||||
int status, const char * /* pContext */,
|
||||
unsigned type, unsigned long count )
|
||||
unsigned type, arrayElementCount count )
|
||||
{
|
||||
struct event_handler_args args;
|
||||
|
||||
|
||||
@@ -46,14 +46,15 @@ void putCallback::completion ()
|
||||
}
|
||||
|
||||
void putCallback::exception (
|
||||
int status, const char * /* pContext */ )
|
||||
int status, const char * /* pContext */,
|
||||
unsigned type, arrayElementCount count )
|
||||
{
|
||||
struct event_handler_args args;
|
||||
|
||||
args.usr = this->pPrivate;
|
||||
args.chid = & this->chan;
|
||||
args.type = TYPENOTCONN;
|
||||
args.count = 0;
|
||||
args.type = type;
|
||||
args.count = count;
|
||||
args.status = status;
|
||||
args.dbr = 0;
|
||||
( *this->pFunc ) (args);
|
||||
|
||||
@@ -47,8 +47,8 @@ recvProcessThread::~recvProcessThread ()
|
||||
|
||||
void recvProcessThread::run ()
|
||||
{
|
||||
int status = ca_attach_context ( this->pcac );
|
||||
SEVCHK ( status, "attaching to client context in recv process thread" );
|
||||
this->pcac->attachToClientCtx ();
|
||||
|
||||
while ( ! this->shutDown ) {
|
||||
|
||||
{
|
||||
|
||||
@@ -22,10 +22,10 @@
|
||||
#undef epicsExportSharedSymbols
|
||||
|
||||
repeaterSubscribeTimer::repeaterSubscribeTimer ( udpiiu &iiuIn, epicsTimerQueue &queueIn ) :
|
||||
timer ( queueIn.createTimer ( *this ) ), iiu ( iiuIn ),
|
||||
timer ( queueIn.createTimer () ), iiu ( iiuIn ),
|
||||
attempts ( 0 ), registered ( false ), once ( false )
|
||||
{
|
||||
this->timer.start ( 10.0 );
|
||||
this->timer.start ( *this, 10.0 );
|
||||
}
|
||||
|
||||
repeaterSubscribeTimer::~repeaterSubscribeTimer ()
|
||||
@@ -33,7 +33,7 @@ repeaterSubscribeTimer::~repeaterSubscribeTimer ()
|
||||
delete & this->timer;
|
||||
}
|
||||
|
||||
epicsTimerNotify::expireStatus repeaterSubscribeTimer::expire ()
|
||||
epicsTimerNotify::expireStatus repeaterSubscribeTimer::expire ( const epicsTime & currentTime )
|
||||
{
|
||||
static const unsigned nTriesToMsg = 50;
|
||||
if ( this->attempts > nTriesToMsg && ! this->once ) {
|
||||
|
||||
@@ -34,7 +34,7 @@ private:
|
||||
unsigned attempts;
|
||||
bool registered;
|
||||
bool once;
|
||||
expireStatus expire ();
|
||||
expireStatus expire ( const epicsTime & currentTime );
|
||||
};
|
||||
|
||||
#endif // ifdef repeaterSubscribeTimerh
|
||||
|
||||
+144
-66
@@ -23,22 +23,35 @@
|
||||
#include "udpiiu.h"
|
||||
#undef epicsExportSharedSymbols
|
||||
|
||||
static const unsigned maxSearchTries = 100u; // max tries on unchanged net
|
||||
static const unsigned initialTriesPerFrame = 1u; // initial UDP frames per search try
|
||||
static const unsigned maxTriesPerFrame = 64u; // max UDP frames per search try
|
||||
|
||||
static const double initialRoundTripEstimate = 0.250; // seconds
|
||||
static const double minSearchPeriod = 0.030; // seconds
|
||||
static const double maxSearchPeriod = 5.0; // seconds
|
||||
|
||||
//
|
||||
// searchTimer::searchTimer ()
|
||||
//
|
||||
searchTimer::searchTimer ( udpiiu &iiuIn, epicsTimerQueue &queueIn, epicsMutex &mutexIn ) :
|
||||
timer ( queueIn.createTimer ( *this ) ),
|
||||
period ( initialRoundTripEstimate * 2.0 ),
|
||||
roundTripDelayEstimate ( initialRoundTripEstimate ),
|
||||
timer ( queueIn.createTimer () ),
|
||||
mutex ( mutexIn ),
|
||||
iiu ( iiuIn ),
|
||||
framesPerTry ( INITIALTRIESPERFRAME ),
|
||||
framesPerTry ( initialTriesPerFrame ),
|
||||
framesPerTryCongestThresh ( UINT_MAX ),
|
||||
minRetry ( UINT_MAX ),
|
||||
retry ( 0u ),
|
||||
searchTriesWithinThisPass ( 0u ),
|
||||
searchResponsesWithinThisPass ( 0u ),
|
||||
searchAttempts ( 0u ),
|
||||
searchResponses ( 0u ),
|
||||
searchAttemptsThisPass ( 0u ),
|
||||
searchResponsesThisPass ( 0u ),
|
||||
retrySeqNo ( 0u ),
|
||||
retrySeqAtPassBegin ( 0u ),
|
||||
period ( CA_RECAST_DELAY )
|
||||
active ( false ),
|
||||
noDelay ( false )
|
||||
{
|
||||
}
|
||||
|
||||
@@ -52,59 +65,68 @@ searchTimer::~searchTimer ()
|
||||
//
|
||||
void searchTimer::resetPeriod ( double delayToNextTry )
|
||||
{
|
||||
bool reschedule;
|
||||
|
||||
if ( delayToNextTry < CA_RECAST_DELAY ) {
|
||||
delayToNextTry = CA_RECAST_DELAY;
|
||||
}
|
||||
|
||||
{
|
||||
epicsAutoMutex locker ( this->mutex );
|
||||
this->retry = 0;
|
||||
if ( this->period > delayToNextTry ) {
|
||||
reschedule = true;
|
||||
bool start;
|
||||
|
||||
delayToNextTry += initialRoundTripEstimate;
|
||||
|
||||
this->retry = 0;
|
||||
if ( this->iiu.channelCount () > 0 ) {
|
||||
if ( this->period > delayToNextTry || ! this->active ) {
|
||||
this->active = true;
|
||||
this->noDelay = delayToNextTry == 0.0;
|
||||
start = true;
|
||||
}
|
||||
else {
|
||||
reschedule = false;
|
||||
start = false;
|
||||
}
|
||||
this->period = CA_RECAST_DELAY;
|
||||
}
|
||||
|
||||
if ( reschedule ) {
|
||||
this->timer.start ( delayToNextTry );
|
||||
debugPrintf ( ("rescheduled search timer for completion in %f sec\n", delayToNextTry) );
|
||||
}
|
||||
else {
|
||||
this->timer.start ( delayToNextTry );
|
||||
debugPrintf ( ("if inactive, search timer started to completion in %f sec\n", delayToNextTry) );
|
||||
start = false;
|
||||
}
|
||||
// upper bound
|
||||
//this->period = initialRoundTripEstimate * 2.0;
|
||||
double newPeriod = this->roundTripDelayEstimate * 2.0;
|
||||
if ( newPeriod <= initialRoundTripEstimate * 2.0 ) {
|
||||
this->period = newPeriod;
|
||||
}
|
||||
else {
|
||||
this->period = initialRoundTripEstimate * 2.0;
|
||||
}
|
||||
// lower bound
|
||||
if ( this->period < minSearchPeriod ) {
|
||||
this->period = minSearchPeriod;
|
||||
}
|
||||
|
||||
if ( start ) {
|
||||
epicsAutoMutexRelease autoRelease ( this->mutex );
|
||||
this->timer.start ( *this, delayToNextTry );
|
||||
// debugPrintf ( ("rescheduled search timer for completion in %f sec\n", delayToNextTry) );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* searchTimer::setRetryInterval ()
|
||||
*/
|
||||
void searchTimer::setRetryInterval (unsigned retryNo)
|
||||
void searchTimer::setRetryInterval ( unsigned retryNo )
|
||||
{
|
||||
unsigned idelay;
|
||||
double delay;
|
||||
|
||||
epicsAutoMutex locker ( this->mutex );
|
||||
|
||||
/*
|
||||
* set the retry number
|
||||
*/
|
||||
this->retry = tsMin ( retryNo, MAXCONNTRIES + 1u );
|
||||
this->retry = tsMin ( retryNo, maxSearchTries + 1u );
|
||||
|
||||
/*
|
||||
* set the retry interval
|
||||
*/
|
||||
idelay = 1u << tsMin ( static_cast < size_t > ( this->retry ),
|
||||
CHAR_BIT * sizeof ( idelay ) - 1u );
|
||||
delay = idelay * CA_RECAST_DELAY; /* sec */
|
||||
/*
|
||||
* place upper limit on the retry delay
|
||||
*/
|
||||
this->period = tsMin ( CA_RECAST_PERIOD, delay );
|
||||
delay = idelay * this->roundTripDelayEstimate * 2.0; /* sec */
|
||||
//delay = idelay * initialRoundTripEstimate * 2.0; /* sec */
|
||||
|
||||
this->period = tsMin ( maxSearchPeriod, delay );
|
||||
this->period = tsMax ( minSearchPeriod, this->period );
|
||||
|
||||
debugPrintf ( ("new CA search period is %f sec\n", this->period) );
|
||||
}
|
||||
@@ -116,31 +138,55 @@ void searchTimer::setRetryInterval (unsigned retryNo)
|
||||
// at least one response. However, dont reset this delay if we
|
||||
// get a delayed response to an old search request.
|
||||
//
|
||||
void searchTimer::notifySearchResponse ( unsigned short retrySeqNoIn )
|
||||
void searchTimer::notifySearchResponse ( unsigned short retrySeqNoIn,
|
||||
const epicsTime & currentTime )
|
||||
{
|
||||
bool reschedualNeeded;
|
||||
|
||||
{
|
||||
epicsAutoMutex locker ( this->mutex );
|
||||
if ( this->retrySeqAtPassBegin <= retrySeqNoIn ) {
|
||||
if ( this->searchResponses < UINT_MAX ) {
|
||||
this->searchResponses++;
|
||||
}
|
||||
}
|
||||
|
||||
if ( this->retrySeqAtPassBegin <= retrySeqNoIn ) {
|
||||
if ( this->searchResponsesWithinThisPass < UINT_MAX ) {
|
||||
this->searchResponsesWithinThisPass++;
|
||||
}
|
||||
}
|
||||
if ( retrySeqNoIn == this->retrySeqNo && ! this->noDelay ) {
|
||||
double curRTT = currentTime - this->timeAtLastRetry;
|
||||
this->roundTripDelayEstimate =
|
||||
( this->roundTripDelayEstimate + curRTT ) / 2.0;
|
||||
this->period = this->roundTripDelayEstimate * 2.0;
|
||||
this->period = tsMin ( maxSearchPeriod, this->period );
|
||||
this->period = tsMax ( minSearchPeriod, this->period );
|
||||
reschedualNeeded = true;
|
||||
this->active = true;
|
||||
this->noDelay = true;
|
||||
}
|
||||
|
||||
reschedualNeeded = ( retrySeqNoIn == this->retrySeqNo );
|
||||
if ( this->searchResponses == this->searchAttempts ) {
|
||||
reschedualNeeded = true;
|
||||
this->active = true;
|
||||
this->noDelay = true;
|
||||
}
|
||||
else {
|
||||
reschedualNeeded = false;
|
||||
}
|
||||
|
||||
if ( reschedualNeeded ) {
|
||||
this->timer.start ( 0.0 );
|
||||
epicsAutoMutexRelease autoRelease (this->mutex );
|
||||
# if defined(DEBUG) && 0
|
||||
char buf[64];
|
||||
epicsTime ts = epicsTime::getCurrent();
|
||||
ts.strftime ( buf, sizeof(buf), "%M:%S.%09f");
|
||||
# endif
|
||||
// debugPrintf ( ( "Response set timer delay to zero. ts=%s, RTT=%f sec\n",
|
||||
// buf, this->roundTripDelayEstimate ) );
|
||||
this->timer.start ( *this, currentTime );
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// searchTimer::expire ()
|
||||
//
|
||||
epicsTimerNotify::expireStatus searchTimer::expire ()
|
||||
epicsTimerNotify::expireStatus searchTimer::expire ( const epicsTime & currentTime )
|
||||
{
|
||||
epicsAutoMutex locker ( this->mutex );
|
||||
unsigned nFrameSent = 0u;
|
||||
@@ -150,6 +196,9 @@ epicsTimerNotify::expireStatus searchTimer::expire ()
|
||||
* check to see if there is nothing to do here
|
||||
*/
|
||||
if ( this->iiu.channelCount () == 0 ) {
|
||||
this->active = false;
|
||||
this->noDelay = false;
|
||||
debugPrintf ( ( "all channels located - search timer terminating\n" ) );
|
||||
return noRestart;
|
||||
}
|
||||
|
||||
@@ -157,6 +206,7 @@ epicsTimerNotify::expireStatus searchTimer::expire ()
|
||||
* increment the retry sequence number
|
||||
*/
|
||||
this->retrySeqNo++; /* allowed to roll over */
|
||||
this->timeAtLastRetry = currentTime;
|
||||
|
||||
/*
|
||||
* dynamically adjust the number of UDP frames per
|
||||
@@ -185,12 +235,12 @@ epicsTimerNotify::expireStatus 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->searchResponsesWithinThisPass >
|
||||
(this->searchTriesWithinThisPass-(this->searchTriesWithinThisPass/16u)) ) {
|
||||
if ( this->searchResponses >
|
||||
( this->searchAttempts - (this->searchAttempts/16u) ) ) {
|
||||
/*
|
||||
* increase UDP frames per try if we have a good score
|
||||
*/
|
||||
if ( this->framesPerTry < MAXTRIESPERFRAME ) {
|
||||
if ( this->framesPerTry < maxTriesPerFrame ) {
|
||||
/*
|
||||
* a congestion avoidance threshold similar to TCP is now used
|
||||
*/
|
||||
@@ -201,24 +251,38 @@ epicsTimerNotify::expireStatus searchTimer::expire ()
|
||||
this->framesPerTry += (this->framesPerTry/8) + 1;
|
||||
}
|
||||
debugPrintf ( ("Increasing frame count to %u t=%u r=%u\n",
|
||||
this->framesPerTry, this->searchTriesWithinThisPass, this->searchResponsesWithinThisPass) );
|
||||
this->framesPerTry, this->searchAttempts, this->searchResponses) );
|
||||
}
|
||||
}
|
||||
/*
|
||||
* if we detect congestion because we have less than a 87.5% success
|
||||
* rate then gradually reduce the frames per try
|
||||
*/
|
||||
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->searchTriesWithinThisPass,
|
||||
this->searchResponsesWithinThisPass) );
|
||||
else if ( this->searchResponses <
|
||||
( this->searchAttempts - (this->searchAttempts/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->searchAttempts, this->searchResponses) );
|
||||
}
|
||||
|
||||
if ( this->searchAttemptsThisPass <= UINT_MAX - this->searchAttempts ) {
|
||||
this->searchAttemptsThisPass += this->searchAttempts;
|
||||
}
|
||||
else {
|
||||
this->searchAttemptsThisPass = UINT_MAX;
|
||||
}
|
||||
if ( this->searchResponsesThisPass <= UINT_MAX - this->searchResponses ) {
|
||||
this->searchResponsesThisPass += this->searchResponses;
|
||||
}
|
||||
else {
|
||||
this->searchResponsesThisPass = UINT_MAX;
|
||||
}
|
||||
this->searchAttempts = 0;
|
||||
this->searchResponses = 0;
|
||||
|
||||
while ( 1 ) {
|
||||
|
||||
/*
|
||||
@@ -228,8 +292,8 @@ epicsTimerNotify::expireStatus searchTimer::expire ()
|
||||
* dont increase the delay between search
|
||||
* requests
|
||||
*/
|
||||
if ( this->searchTriesWithinThisPass >= this->iiu.channelCount () ) {
|
||||
if ( this->searchResponsesWithinThisPass == 0u ) {
|
||||
if ( this->searchAttemptsThisPass >= this->iiu.channelCount () ) {
|
||||
if ( this->searchResponsesThisPass == 0u ) {
|
||||
debugPrintf ( ("increasing search try interval\n") );
|
||||
this->setRetryInterval ( this->minRetry + 1u );
|
||||
}
|
||||
@@ -250,8 +314,8 @@ epicsTimerNotify::expireStatus searchTimer::expire ()
|
||||
*/
|
||||
this->retrySeqAtPassBegin = this->retrySeqNo;
|
||||
|
||||
this->searchTriesWithinThisPass = 0;
|
||||
this->searchResponsesWithinThisPass = 0;
|
||||
this->searchAttemptsThisPass = 0;
|
||||
this->searchResponsesThisPass = 0;
|
||||
|
||||
debugPrintf ( ("saw end of list\n") );
|
||||
}
|
||||
@@ -275,8 +339,8 @@ epicsTimerNotify::expireStatus searchTimer::expire ()
|
||||
this->minRetry = retryNoForThisChannel;
|
||||
}
|
||||
|
||||
if ( this->searchTriesWithinThisPass < UINT_MAX ) {
|
||||
this->searchTriesWithinThisPass++;
|
||||
if ( this->searchAttempts < UINT_MAX ) {
|
||||
this->searchAttempts++;
|
||||
}
|
||||
if ( nChanSent < UINT_MAX ) {
|
||||
nChanSent++;
|
||||
@@ -308,15 +372,29 @@ epicsTimerNotify::expireStatus searchTimer::expire ()
|
||||
// flush out the search request buffer
|
||||
this->iiu.datagramFlush ();
|
||||
|
||||
debugPrintf ( ("sent %u delay sec=%f\n", nFrameSent, this->period) );
|
||||
# ifdef DEBUG
|
||||
char buf[64];
|
||||
epicsTime ts = epicsTime::getCurrent();
|
||||
ts.strftime ( buf, sizeof(buf), "%M:%S.%09f");
|
||||
debugPrintf ( ("sent %u delay sec=%f RTT=%f ts=%s\n",
|
||||
nFrameSent, this->period,
|
||||
this->roundTripDelayEstimate, buf ) );
|
||||
# endif
|
||||
|
||||
if ( this->iiu.channelCount () == 0 ) {
|
||||
debugPrintf ( ( "all channels connected\n" ) );
|
||||
this->active = false;
|
||||
this->noDelay = false;
|
||||
return noRestart;
|
||||
}
|
||||
else if ( this->retry < MAXCONNTRIES ) {
|
||||
else if ( this->retry < maxSearchTries ) {
|
||||
this->noDelay = this->period == 0.0;
|
||||
return expireStatus ( restart, this->period );
|
||||
}
|
||||
else {
|
||||
debugPrintf ( ( "maximum search tries exceeded - giving up\n" ) );
|
||||
this->active = false;
|
||||
this->noDelay = false;
|
||||
return noRestart;
|
||||
}
|
||||
}
|
||||
|
||||
+12
-6
@@ -27,10 +27,13 @@ class searchTimer : private epicsTimerNotify {
|
||||
public:
|
||||
searchTimer ( udpiiu &iiu, epicsTimerQueue &queue, epicsMutex & );
|
||||
virtual ~searchTimer ();
|
||||
void notifySearchResponse ( unsigned short retrySeqNo );
|
||||
void notifySearchResponse ( unsigned short retrySeqNo, const epicsTime & currentTime );
|
||||
void resetPeriod ( double delayToNextTry );
|
||||
void show ( unsigned level ) const;
|
||||
private:
|
||||
epicsTime timeAtLastRetry;
|
||||
double period; /* period between tries */
|
||||
double roundTripDelayEstimate;
|
||||
epicsTimer &timer;
|
||||
epicsMutex &mutex;
|
||||
udpiiu &iiu;
|
||||
@@ -38,13 +41,16 @@ private:
|
||||
unsigned framesPerTryCongestThresh; /* one half N tries w congest */
|
||||
unsigned minRetry; /* min retry number so far */
|
||||
unsigned retry;
|
||||
unsigned searchTriesWithinThisPass; /* num search tries within this pass through the list */
|
||||
unsigned searchResponsesWithinThisPass; /* num search resp within this pass through the list */
|
||||
unsigned searchAttempts; /* num search tries within this timer experation */
|
||||
unsigned searchResponses; /* num search resp within this timer experation */
|
||||
unsigned searchAttemptsThisPass; /* num search tries within this pass */
|
||||
unsigned searchResponsesThisPass; /* num search resp within this pass */
|
||||
unsigned short retrySeqNo; /* search retry seq number */
|
||||
unsigned short retrySeqAtPassBegin; /* search retry seq number at beg of pass through list */
|
||||
double period; /* period between tries */
|
||||
expireStatus expire ();
|
||||
void setRetryInterval (unsigned retryNo);
|
||||
bool active;
|
||||
bool noDelay;
|
||||
expireStatus expire ( const epicsTime & currentTime );
|
||||
void setRetryInterval ( unsigned retryNo );
|
||||
};
|
||||
|
||||
#endif // ifdef searchTimerh
|
||||
|
||||
+9
-9
@@ -58,7 +58,7 @@ public:
|
||||
static syncGroupReadNotify * factory (
|
||||
tsFreeList < class syncGroupReadNotify, 128 > &,
|
||||
struct CASG &, chid, unsigned type,
|
||||
unsigned long count, void *pValueIn );
|
||||
arrayElementCount count, void *pValueIn );
|
||||
void destroy ( casgRecycle & );
|
||||
void show ( unsigned level ) const;
|
||||
protected:
|
||||
@@ -66,7 +66,7 @@ protected:
|
||||
private:
|
||||
void *pValue;
|
||||
syncGroupReadNotify ( struct CASG &sgIn, chid,
|
||||
unsigned type, unsigned long count, void *pValueIn );
|
||||
unsigned type, arrayElementCount count, void *pValueIn );
|
||||
void * operator new ( size_t,
|
||||
tsFreeList < class syncGroupReadNotify, 128 > & );
|
||||
# if ! defined ( NO_PLACEMENT_DELETE )
|
||||
@@ -74,9 +74,9 @@ private:
|
||||
tsFreeList < class syncGroupReadNotify, 128 > & );
|
||||
# endif
|
||||
void completion (
|
||||
unsigned type, unsigned long count, const void *pData );
|
||||
unsigned type, arrayElementCount count, const void *pData );
|
||||
void exception (
|
||||
int status, const char *pContext, unsigned type, unsigned long count );
|
||||
int status, const char *pContext, unsigned type, arrayElementCount count );
|
||||
};
|
||||
|
||||
class syncGroupWriteNotify : public syncGroupNotify, public cacWriteNotify {
|
||||
@@ -84,7 +84,7 @@ public:
|
||||
static syncGroupWriteNotify * factory (
|
||||
tsFreeList < class syncGroupWriteNotify, 128 > &,
|
||||
struct CASG &, chid, unsigned type,
|
||||
unsigned long count, const void *pValueIn );
|
||||
arrayElementCount count, const void *pValueIn );
|
||||
void destroy ( casgRecycle & );
|
||||
void show ( unsigned level ) const;
|
||||
protected:
|
||||
@@ -92,7 +92,7 @@ protected:
|
||||
private:
|
||||
void *pValue;
|
||||
syncGroupWriteNotify ( struct CASG &, chid, unsigned type,
|
||||
unsigned long count, const void *pValueIn );
|
||||
arrayElementCount count, const void *pValueIn );
|
||||
void * operator new ( size_t,
|
||||
tsFreeList < class syncGroupWriteNotify, 128 > & );
|
||||
# if ! defined ( NO_PLACEMENT_DELETE )
|
||||
@@ -100,7 +100,7 @@ private:
|
||||
tsFreeList < class syncGroupWriteNotify, 128 > & );
|
||||
# endif
|
||||
void completion ();
|
||||
void exception (int status, const char *pContext );
|
||||
void exception ( int status, const char *pContext, unsigned type, arrayElementCount count );
|
||||
};
|
||||
|
||||
class oldCAC;
|
||||
@@ -114,8 +114,8 @@ public:
|
||||
int block ( double timeout );
|
||||
void reset ();
|
||||
void show ( unsigned level ) const;
|
||||
int get ( chid pChan, unsigned type, unsigned long count, void *pValue );
|
||||
int put ( chid pChan, unsigned type, unsigned long count, const void *pValue );
|
||||
int get ( chid pChan, unsigned type, arrayElementCount count, void *pValue );
|
||||
int put ( chid pChan, unsigned type, arrayElementCount count, const void *pValue );
|
||||
void destroyIO ( syncGroupNotify & );
|
||||
void * operator new ( size_t size );
|
||||
void operator delete ( void *pCadaver, size_t size );
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
#include "oldAccess.h"
|
||||
|
||||
syncGroupReadNotify::syncGroupReadNotify ( CASG &sgIn, chid pChan,
|
||||
unsigned type, unsigned long count, void *pValueIn ) :
|
||||
unsigned type, arrayElementCount count, void *pValueIn ) :
|
||||
syncGroupNotify ( sgIn, pChan ), pValue ( pValueIn )
|
||||
{
|
||||
pChan->read ( type, count, *this, &this->id );
|
||||
@@ -45,7 +45,7 @@ syncGroupReadNotify::syncGroupReadNotify ( CASG &sgIn, chid pChan,
|
||||
syncGroupReadNotify * syncGroupReadNotify::factory (
|
||||
tsFreeList < class syncGroupReadNotify, 128 > &freeList,
|
||||
struct CASG &sg, chid chan, unsigned type,
|
||||
unsigned long count, void *pValueIn )
|
||||
arrayElementCount count, void *pValueIn )
|
||||
{
|
||||
return new ( freeList ) syncGroupReadNotify ( sg, chan, type,
|
||||
count, pValueIn);
|
||||
@@ -62,7 +62,7 @@ syncGroupReadNotify::~syncGroupReadNotify ()
|
||||
}
|
||||
|
||||
void syncGroupReadNotify::completion (
|
||||
unsigned type, unsigned long count, const void *pData )
|
||||
unsigned type, arrayElementCount count, const void *pData )
|
||||
{
|
||||
if ( this->magic != CASG_MAGIC ) {
|
||||
this->sg.printf ( "cac: sync group io_complete(): bad sync grp op magic number?\n" );
|
||||
@@ -79,7 +79,7 @@ void syncGroupReadNotify::completion (
|
||||
}
|
||||
|
||||
void syncGroupReadNotify::exception (
|
||||
int status, const char *pContext, unsigned type, unsigned long count )
|
||||
int status, const char *pContext, unsigned type, arrayElementCount count )
|
||||
{
|
||||
ca_signal_formated ( status, __FILE__, __LINE__,
|
||||
"CA sync group read request failed with chan=%s type=%d count=%ld because \"%s\"\n",
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
#include "oldAccess.h"
|
||||
|
||||
syncGroupWriteNotify::syncGroupWriteNotify ( CASG &sgIn, chid pChan, unsigned type,
|
||||
unsigned long count, const void *pValueIn ) :
|
||||
arrayElementCount count, const void *pValueIn ) :
|
||||
syncGroupNotify ( sgIn, pChan )
|
||||
{
|
||||
pChan->write ( type, count, pValueIn, *this, &this->id );
|
||||
@@ -45,7 +45,7 @@ syncGroupWriteNotify::syncGroupWriteNotify ( CASG &sgIn, chid pChan, unsigned ty
|
||||
syncGroupWriteNotify * syncGroupWriteNotify::factory (
|
||||
tsFreeList < class syncGroupWriteNotify, 128 > &freeList,
|
||||
struct CASG &sg, chid chan, unsigned type,
|
||||
unsigned long count, const void *pValueIn )
|
||||
arrayElementCount count, const void *pValueIn )
|
||||
{
|
||||
return new ( freeList ) syncGroupWriteNotify ( sg, chan, type,
|
||||
count, pValueIn);
|
||||
@@ -73,11 +73,11 @@ void syncGroupWriteNotify::completion ()
|
||||
}
|
||||
|
||||
void syncGroupWriteNotify::exception (
|
||||
int status, const char *pContext )
|
||||
int status, const char *pContext, unsigned type, arrayElementCount count )
|
||||
{
|
||||
ca_signal_formated ( status, __FILE__, __LINE__,
|
||||
"CA sync group write request for channel \"%s\" failed because \"%s\"\n",
|
||||
this->chan->pName(), pContext);
|
||||
"CA sync group write request for channel \"%s\" failed because \"%s\" type=%s count=%u\n",
|
||||
this->chan->pName(), pContext, dbr_type_to_text ( type ), count);
|
||||
//
|
||||
// This notify is left installed at this point as a place holder indicating that
|
||||
// all requests have not been completed. This notify is not uninstalled until
|
||||
|
||||
+7
-5
@@ -189,12 +189,12 @@ extern "C" int epicsShareAPI ca_sg_test ( const CA_SYNC_GID gid )
|
||||
* ca_sg_array_put()
|
||||
*/
|
||||
extern "C" int epicsShareAPI ca_sg_array_put ( const CA_SYNC_GID gid, chtype type,
|
||||
unsigned long count, chid pChan, const void *pValue )
|
||||
arrayElementCount count, chid pChan, const void *pValue )
|
||||
{
|
||||
CASG *pcasg;
|
||||
oldCAC *pcac;
|
||||
int caStatus;
|
||||
|
||||
|
||||
caStatus = fetchClientContext ( &pcac );
|
||||
if ( caStatus != ECA_NORMAL ) {
|
||||
return caStatus;
|
||||
@@ -205,14 +205,15 @@ extern "C" int epicsShareAPI ca_sg_array_put ( const CA_SYNC_GID gid, chtype typ
|
||||
return ECA_BADSYNCGRP;
|
||||
}
|
||||
|
||||
return pcasg->put ( pChan, type, count, pValue );
|
||||
return pcasg->put ( pChan, type,
|
||||
static_cast < unsigned > ( count ), pValue );
|
||||
}
|
||||
|
||||
/*
|
||||
* ca_sg_array_get()
|
||||
*/
|
||||
extern "C" int epicsShareAPI ca_sg_array_get ( const CA_SYNC_GID gid, chtype type,
|
||||
unsigned long count, chid pChan, void *pValue )
|
||||
arrayElementCount count, chid pChan, void *pValue )
|
||||
{
|
||||
CASG *pcasg;
|
||||
oldCAC *pcac;
|
||||
@@ -228,5 +229,6 @@ extern "C" int epicsShareAPI ca_sg_array_get ( const CA_SYNC_GID gid, chtype typ
|
||||
return ECA_BADSYNCGRP;
|
||||
}
|
||||
|
||||
return pcasg->get ( pChan, type, count, pValue );
|
||||
return pcasg->get ( pChan, type,
|
||||
static_cast < unsigned > ( count ), pValue );
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
//
|
||||
tcpRecvWatchdog::tcpRecvWatchdog
|
||||
( tcpiiu &iiuIn, double periodIn, epicsTimerQueue & queueIn ) :
|
||||
period ( periodIn ), timer ( queueIn.createTimer ( *this ) ),
|
||||
period ( periodIn ), timer ( queueIn.createTimer () ),
|
||||
iiu ( iiuIn ), responsePending ( false ),
|
||||
beaconAnomaly ( true )
|
||||
{
|
||||
@@ -31,7 +31,7 @@ tcpRecvWatchdog::~tcpRecvWatchdog ()
|
||||
delete & this->timer;
|
||||
}
|
||||
|
||||
epicsTimerNotify::expireStatus tcpRecvWatchdog::expire ()
|
||||
epicsTimerNotify::expireStatus tcpRecvWatchdog::expire ( const epicsTime & currentTime )
|
||||
{
|
||||
if ( this->responsePending ) {
|
||||
this->cancel ();
|
||||
@@ -52,7 +52,7 @@ epicsTimerNotify::expireStatus tcpRecvWatchdog::expire ()
|
||||
void tcpRecvWatchdog::beaconArrivalNotify ()
|
||||
{
|
||||
if ( ! this->beaconAnomaly && ! this->responsePending ) {
|
||||
this->timer.start ( this->period );
|
||||
this->timer.start ( *this, this->period );
|
||||
debugPrintf ( ("Saw a normal beacon - reseting TCP recv watchdog\n") );
|
||||
}
|
||||
}
|
||||
@@ -74,13 +74,35 @@ void tcpRecvWatchdog::messageArrivalNotify ()
|
||||
{
|
||||
this->beaconAnomaly = false;
|
||||
this->responsePending = false;
|
||||
this->timer.start ( this->period );
|
||||
this->timer.start ( *this, this->period );
|
||||
debugPrintf ( ("received a message - reseting TCP recv watchdog\n") );
|
||||
}
|
||||
|
||||
//
|
||||
// The thread for outgoing requests in the client runs
|
||||
// at a higher priority than the thread in the client
|
||||
// that receives responses. Therefore, there could
|
||||
// be considerable large array write send backlog that
|
||||
// is delaying departure of an echo request and also
|
||||
// interrupting delivery of an echo response.
|
||||
// We must be careful not to timeout the echo response as
|
||||
// long as we see indication of regular departures of
|
||||
// message buffers from the client in a situation where
|
||||
// we know that the TCP send queueing has been exceeded.
|
||||
// The send watchdog will be responsible for detecting
|
||||
// dead connections in this case.
|
||||
//
|
||||
void tcpRecvWatchdog::sendBacklogProgressNotify ()
|
||||
{
|
||||
this->beaconAnomaly = false;
|
||||
this->responsePending = false;
|
||||
this->timer.start ( *this, this->period );
|
||||
debugPrintf ( ("saw heavy send backlog - reseting TCP recv watchdog\n") );
|
||||
}
|
||||
|
||||
void tcpRecvWatchdog::connectNotify ()
|
||||
{
|
||||
this->timer.start ( this->period );
|
||||
this->timer.start ( *this, this->period );
|
||||
debugPrintf ( ("connected to the server - reseting TCP recv watchdog\n") );
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
tcpSendWatchdog::tcpSendWatchdog
|
||||
( tcpiiu &iiuIn, double periodIn, epicsTimerQueue & queueIn ) :
|
||||
period ( periodIn ), timer ( queueIn.createTimer ( *this ) ),
|
||||
period ( periodIn ), timer ( queueIn.createTimer () ),
|
||||
iiu ( iiuIn )
|
||||
{
|
||||
}
|
||||
@@ -27,7 +27,7 @@ tcpSendWatchdog::~tcpSendWatchdog ()
|
||||
delete & this->timer;
|
||||
}
|
||||
|
||||
epicsTimerNotify::expireStatus tcpSendWatchdog::expire ()
|
||||
epicsTimerNotify::expireStatus tcpSendWatchdog::expire ( const epicsTime & currentTime )
|
||||
{
|
||||
char hostName[128];
|
||||
this->iiu.hostName ( hostName, sizeof ( hostName ) );
|
||||
@@ -39,7 +39,7 @@ epicsTimerNotify::expireStatus tcpSendWatchdog::expire ()
|
||||
|
||||
void tcpSendWatchdog::start ()
|
||||
{
|
||||
this->timer.start ( this->period );
|
||||
this->timer.start ( *this, this->period );
|
||||
}
|
||||
|
||||
void tcpSendWatchdog::cancel ()
|
||||
|
||||
+417
-482
File diff suppressed because it is too large
Load Diff
@@ -22,26 +22,26 @@ extern "C" void epicsShareAPI ca_test_event ( struct event_handler_args args )
|
||||
|
||||
switch ( args.type ) {
|
||||
case DBR_STRING:
|
||||
printf ( "CAC: Value:\t<%s>\n", (const char *) args.dbr );
|
||||
printf ( "CAC: Value:\t<%s>\n", (dbr_string_t *) args.dbr );
|
||||
break;
|
||||
case DBR_CHAR:
|
||||
printf ( "CAC: Value:\t<%d>\n", *(char *) args.dbr );
|
||||
printf ( "CAC: Value:\t<%d>\n", *(dbr_char_t *) args.dbr );
|
||||
break;
|
||||
#if DBR_INT != DBR_SHORT
|
||||
case DBR_INT:
|
||||
#endif
|
||||
case DBR_SHORT:
|
||||
case DBR_ENUM:
|
||||
printf ( "CAC: Value:\t<%d>\n", *(short *) args.dbr );
|
||||
printf ( "CAC: Value:\t<%d>\n", *(dbr_short_t *) args.dbr );
|
||||
break;
|
||||
case DBR_LONG:
|
||||
printf ( "CAC: Value:\t<%ld>\n", *(long *)args.dbr );
|
||||
printf ( "CAC: Value:\t<%ld>\n", *(dbr_long_t *)args.dbr );
|
||||
break;
|
||||
case DBR_FLOAT:
|
||||
printf ( "CAC: Value:\t<%f>\n", *(float *)args.dbr );
|
||||
printf ( "CAC: Value:\t<%f>\n", *(dbr_float_t *)args.dbr );
|
||||
break;
|
||||
case DBR_DOUBLE:
|
||||
printf ( "CAC: Value:\t<%f>\n", *(double *)args.dbr );
|
||||
printf ( "CAC: Value:\t<%f>\n", *(dbr_double_t *)args.dbr );
|
||||
break;
|
||||
case DBR_STS_STRING:
|
||||
printf ( "CAC: Value:\t<%s>\n", ((struct dbr_sts_string *)args.dbr)->value );
|
||||
|
||||
+41
-31
@@ -135,7 +135,7 @@ udpiiu::udpiiu ( cac &cac ) :
|
||||
this->recvThreadExitSignal = epicsEventMustCreate ( epicsEventEmpty );
|
||||
if ( ! this->recvThreadExitSignal ) {
|
||||
socket_close ( this->sock );
|
||||
throwWithLocation ( noMemory () );
|
||||
throwWithLocation ( std::bad_alloc () );
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -164,7 +164,7 @@ udpiiu::udpiiu ( cac &cac ) :
|
||||
this->printf ("CA: unable to create UDP receive thread\n");
|
||||
epicsEventDestroy (this->recvThreadExitSignal);
|
||||
socket_close (this->sock);
|
||||
throwWithLocation ( noMemory () );
|
||||
throwWithLocation ( std::bad_alloc () );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -232,8 +232,8 @@ void udpiiu::recvMsg ()
|
||||
SOCKERRSTR (errnoCpy) );
|
||||
}
|
||||
else if ( status > 0 ) {
|
||||
this->postMsg ( src,
|
||||
this->recvBuf, (unsigned long) status );
|
||||
this->postMsg ( src, this->recvBuf, (arrayElementCount) status,
|
||||
epicsTime::getCurrent() );
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -485,21 +485,25 @@ void udpiiu::shutdown ()
|
||||
epicsEventMustWait ( this->recvThreadExitSignal );
|
||||
}
|
||||
|
||||
bool udpiiu::badUDPRespAction ( const caHdr &msg, const osiSockAddr &netAddr )
|
||||
bool udpiiu::badUDPRespAction ( const caHdr &msg,
|
||||
const osiSockAddr &netAddr, const epicsTime ¤tTime )
|
||||
{
|
||||
char buf[64];
|
||||
sockAddrToDottedIP ( &netAddr.sa, buf, sizeof ( buf ) );
|
||||
this->printf ( "CAC: undecipherable ( bad msg code %u ) UDP message from %s\n",
|
||||
msg.m_cmmd, buf );
|
||||
char date[64];
|
||||
currentTime.strftime ( date, sizeof ( date ), "%a %b %d %Y %H:%M:%S");
|
||||
this->printf ( "CAC: undecipherable ( bad msg code %u ) UDP message from %s at %s\n",
|
||||
msg.m_cmmd, buf, date );
|
||||
return false;
|
||||
}
|
||||
|
||||
bool udpiiu::noopAction ( const caHdr &, const osiSockAddr & )
|
||||
bool udpiiu::noopAction ( const caHdr &, const osiSockAddr &, const epicsTime & )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool udpiiu::searchRespAction ( const caHdr &msg, const osiSockAddr &addr )
|
||||
bool udpiiu::searchRespAction ( const caHdr &msg,
|
||||
const osiSockAddr &addr, const epicsTime ¤tTime )
|
||||
{
|
||||
osiSockAddr serverAddr;
|
||||
unsigned minorVersion;
|
||||
@@ -527,7 +531,7 @@ bool udpiiu::searchRespAction ( const caHdr &msg, const osiSockAddr &addr )
|
||||
* so that we can have multiple servers on one host
|
||||
*/
|
||||
serverAddr.ia.sin_family = AF_INET;
|
||||
if ( CA_V48 ( CA_PROTOCOL_VERSION,minorVersion ) ) {
|
||||
if ( CA_V48 ( minorVersion ) ) {
|
||||
if ( msg.m_cid != INADDR_BROADCAST ) {
|
||||
/*
|
||||
* Leave address in network byte order (m_cid has not been
|
||||
@@ -540,7 +544,7 @@ bool udpiiu::searchRespAction ( const caHdr &msg, const osiSockAddr &addr )
|
||||
}
|
||||
serverAddr.ia.sin_port = htons ( msg.m_dataType );
|
||||
}
|
||||
else if ( CA_V45 (CA_PROTOCOL_VERSION,minorVersion) ) {
|
||||
else if ( CA_V45 (minorVersion) ) {
|
||||
serverAddr.ia.sin_port = htons ( msg.m_dataType );
|
||||
serverAddr.ia.sin_addr = addr.ia.sin_addr;
|
||||
}
|
||||
@@ -549,19 +553,20 @@ bool udpiiu::searchRespAction ( const caHdr &msg, const osiSockAddr &addr )
|
||||
serverAddr.ia.sin_addr = addr.ia.sin_addr;
|
||||
}
|
||||
|
||||
if ( CA_V42 ( CA_PROTOCOL_VERSION, minorVersion ) ) {
|
||||
if ( CA_V42 ( minorVersion ) ) {
|
||||
return this->pCAC ()->lookupChannelAndTransferToTCP
|
||||
( msg.m_available, msg.m_cid, USHRT_MAX,
|
||||
0, minorVersion, serverAddr );
|
||||
( msg.m_available, msg.m_cid, 0xffff,
|
||||
0, minorVersion, serverAddr, currentTime );
|
||||
}
|
||||
else {
|
||||
return this->pCAC ()->lookupChannelAndTransferToTCP
|
||||
( msg.m_available, msg.m_cid, msg.m_dataType,
|
||||
msg.m_count, minorVersion, serverAddr );
|
||||
msg.m_count, minorVersion, serverAddr, currentTime );
|
||||
}
|
||||
}
|
||||
|
||||
bool udpiiu::beaconAction ( const caHdr &msg, const osiSockAddr &net_addr )
|
||||
bool udpiiu::beaconAction ( const caHdr &msg,
|
||||
const osiSockAddr &net_addr, const epicsTime ¤tTime )
|
||||
{
|
||||
struct sockaddr_in ina;
|
||||
|
||||
@@ -596,49 +601,54 @@ bool udpiiu::beaconAction ( const caHdr &msg, const osiSockAddr &net_addr )
|
||||
ina.sin_port = htons ( this->serverPort );
|
||||
}
|
||||
|
||||
this->pCAC ()->beaconNotify ( ina );
|
||||
this->pCAC ()->beaconNotify ( ina, currentTime );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool udpiiu::repeaterAckAction ( const caHdr &, const osiSockAddr &)
|
||||
bool udpiiu::repeaterAckAction ( const caHdr &,
|
||||
const osiSockAddr &, const epicsTime &)
|
||||
{
|
||||
this->pCAC ()->repeaterSubscribeConfirmNotify ();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool udpiiu::notHereRespAction ( const caHdr &, const osiSockAddr &)
|
||||
bool udpiiu::notHereRespAction ( const caHdr &,
|
||||
const osiSockAddr &, const epicsTime & )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool udpiiu::exceptionRespAction ( const caHdr &msg, const osiSockAddr &net_addr )
|
||||
bool udpiiu::exceptionRespAction ( const caHdr &msg,
|
||||
const osiSockAddr &net_addr, const epicsTime ¤tTime )
|
||||
{
|
||||
const caHdr &reqMsg = * ( &msg + 1 );
|
||||
char name[64];
|
||||
|
||||
sockAddrToDottedIP ( &net_addr.sa, name, sizeof ( name ) );
|
||||
char date[64];
|
||||
currentTime.strftime ( date, sizeof ( date ), "%a %b %d %Y %H:%M:%S");
|
||||
|
||||
if ( msg.m_postsize > sizeof ( caHdr ) ){
|
||||
errlogPrintf ( "error condition \"%s\" detected by %s with context \"%s\"\n",
|
||||
errlogPrintf ( "error condition \"%s\" detected by %s with context \"%s\" at %s\n",
|
||||
ca_message ( htonl ( msg.m_available ) ),
|
||||
name, reinterpret_cast <const char *> ( &reqMsg + 1 ) );
|
||||
name, reinterpret_cast <const char *> ( &reqMsg + 1 ), date );
|
||||
}
|
||||
else{
|
||||
errlogPrintf ( "error condition \"%s\" detected by %s\n",
|
||||
ca_message ( htonl ( msg.m_available ) ), name );
|
||||
errlogPrintf ( "error condition \"%s\" detected by %s at %s\n",
|
||||
ca_message ( htonl ( msg.m_available ) ), name, date );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void udpiiu::postMsg ( const osiSockAddr &net_addr,
|
||||
char *pInBuf, unsigned long blockSize )
|
||||
char *pInBuf, arrayElementCount blockSize,
|
||||
const epicsTime ¤tTime)
|
||||
{
|
||||
caHdr *pCurMsg;
|
||||
|
||||
while ( blockSize ) {
|
||||
unsigned long size;
|
||||
arrayElementCount size;
|
||||
|
||||
if ( blockSize < sizeof ( *pCurMsg ) ) {
|
||||
char buf[64];
|
||||
@@ -694,7 +704,7 @@ void udpiiu::postMsg ( const osiSockAddr &net_addr,
|
||||
else {
|
||||
pStub = &udpiiu::badUDPRespAction;
|
||||
}
|
||||
bool success = ( this->*pStub ) ( *pCurMsg, net_addr );
|
||||
bool success = ( this->*pStub ) ( *pCurMsg, net_addr, currentTime );
|
||||
if ( ! success ) {
|
||||
char buf[256];
|
||||
sockAddrToDottedIP ( &net_addr.sa, buf, sizeof ( buf ) );
|
||||
@@ -712,9 +722,9 @@ void udpiiu::postMsg ( const osiSockAddr &net_addr,
|
||||
*/
|
||||
bool udpiiu::pushDatagramMsg ( const caHdr &msg, const void *pExt, ca_uint16_t extsize )
|
||||
{
|
||||
unsigned long msgsize;
|
||||
ca_uint16_t allignedExtSize;
|
||||
caHdr *pbufmsg;
|
||||
arrayElementCount msgsize;
|
||||
ca_uint16_t allignedExtSize;
|
||||
caHdr *pbufmsg;
|
||||
|
||||
allignedExtSize = CA_MESSAGE_ALIGN ( extsize );
|
||||
msgsize = sizeof ( caHdr ) + allignedExtSize;
|
||||
|
||||
+20
-10
@@ -39,6 +39,8 @@ epicsShareFunc void epicsShareAPI caRepeaterRegistrationMessage ( SOCKET sock, u
|
||||
extern "C" epicsShareFunc void caRepeaterThread ( void *pDummy );
|
||||
epicsShareFunc void ca_repeater ( void );
|
||||
|
||||
class epicsTime;
|
||||
|
||||
class udpiiu : public netiiu {
|
||||
public:
|
||||
udpiiu ( class cac & );
|
||||
@@ -46,7 +48,8 @@ public:
|
||||
void shutdown ();
|
||||
void recvMsg ();
|
||||
void postMsg ( const osiSockAddr &net_addr,
|
||||
char *pInBuf, unsigned long blockSize );
|
||||
char *pInBuf, arrayElementCount blockSize,
|
||||
const epicsTime ¤Time);
|
||||
void repeaterRegistrationMessage ( unsigned attemptNumber );
|
||||
void datagramFlush ();
|
||||
unsigned getPort () const;
|
||||
@@ -55,7 +58,6 @@ public:
|
||||
|
||||
// exceptions
|
||||
class noSocket {};
|
||||
class noMemory {};
|
||||
|
||||
SOCKET getSock () const;
|
||||
|
||||
@@ -75,19 +77,27 @@ private:
|
||||
|
||||
bool pushDatagramMsg ( const caHdr &msg, const void *pExt, ca_uint16_t extsize );
|
||||
|
||||
typedef bool ( udpiiu::*pProtoStubUDP ) ( const caHdr &, const osiSockAddr & );
|
||||
typedef bool ( udpiiu::*pProtoStubUDP ) ( const caHdr &,
|
||||
const osiSockAddr &, const epicsTime & );
|
||||
|
||||
// UDP protocol dispatch table
|
||||
static const pProtoStubUDP udpJumpTableCAC[];
|
||||
|
||||
// UDP protocol stubs
|
||||
bool noopAction ( const caHdr &, const osiSockAddr & );
|
||||
bool badUDPRespAction ( const caHdr &msg, const osiSockAddr &netAddr );
|
||||
bool searchRespAction ( const caHdr &msg, const osiSockAddr &net_addr );
|
||||
bool exceptionRespAction ( const caHdr &msg, const osiSockAddr &net_addr );
|
||||
bool beaconAction ( const caHdr &msg, const osiSockAddr &net_addr );
|
||||
bool notHereRespAction ( const caHdr &msg, const osiSockAddr &net_addr );
|
||||
bool repeaterAckAction ( const caHdr &msg, const osiSockAddr &net_addr );
|
||||
bool noopAction ( const caHdr &,
|
||||
const osiSockAddr &, const epicsTime & );
|
||||
bool badUDPRespAction ( const caHdr &msg,
|
||||
const osiSockAddr &netAddr, const epicsTime & );
|
||||
bool searchRespAction ( const caHdr &msg,
|
||||
const osiSockAddr &net_addr, const epicsTime & );
|
||||
bool exceptionRespAction ( const caHdr &msg,
|
||||
const osiSockAddr &net_addr, const epicsTime & );
|
||||
bool beaconAction ( const caHdr &msg,
|
||||
const osiSockAddr &net_addr, const epicsTime & );
|
||||
bool notHereRespAction ( const caHdr &msg,
|
||||
const osiSockAddr &net_addr, const epicsTime & );
|
||||
bool repeaterAckAction ( const caHdr &msg,
|
||||
const osiSockAddr &net_addr, const epicsTime & );
|
||||
|
||||
friend void cacRecvThreadUDP ( void *pParam );
|
||||
};
|
||||
|
||||
+195
-170
@@ -21,33 +21,23 @@
|
||||
#include <new> // needed by comQueueSend
|
||||
|
||||
#include "epicsTimer.h"
|
||||
#include "epicsMemory.h"
|
||||
#include "ipAddrToAsciiAsynchronous.h"
|
||||
#include "osiWireFormat.h"
|
||||
|
||||
#include "comBuf.h"
|
||||
#include "netiiu.h"
|
||||
|
||||
enum iiu_conn_state {iiu_connecting, iiu_connected, iiu_disconnected};
|
||||
enum iiu_conn_state { iiu_connecting, iiu_connected, iiu_disconnected };
|
||||
|
||||
class nciu;
|
||||
class tcpiiu;
|
||||
|
||||
class bufferReservoir {
|
||||
public:
|
||||
~bufferReservoir ();
|
||||
void addOneBuffer ();
|
||||
comBuf *fetchOneBuffer ();
|
||||
unsigned nBytes ();
|
||||
void drain ();
|
||||
private:
|
||||
tsDLList < comBuf > reservedBufs;
|
||||
};
|
||||
|
||||
class comQueSend {
|
||||
public:
|
||||
comQueSend ( wireSendAdapter & );
|
||||
~comQueSend ();
|
||||
void clear ();
|
||||
void reserveSpace ( unsigned msgSize );
|
||||
unsigned occupiedBytes () const;
|
||||
bool flushEarlyThreshold ( unsigned nBytesThisMsg ) const;
|
||||
bool flushBlockThreshold ( unsigned nBytesThisMsg ) const;
|
||||
@@ -55,13 +45,12 @@ public:
|
||||
void pushUInt16 ( const ca_uint16_t value );
|
||||
void pushUInt32 ( const ca_uint32_t value );
|
||||
void pushFloat32 ( const ca_float32_t value );
|
||||
void pushString ( const char *pVal, unsigned nElem );
|
||||
void pushString ( const char *pVal, unsigned nChar );
|
||||
void push_dbr_type ( unsigned type, const void *pVal, unsigned nElem );
|
||||
comBuf * popNextComBufToSend ();
|
||||
private:
|
||||
wireSendAdapter & wire;
|
||||
tsDLList < comBuf > bufs;
|
||||
bufferReservoir reservoir;
|
||||
unsigned nBytesPending;
|
||||
void copy_dbr_string ( const void *pValue, unsigned nElem );
|
||||
void copy_dbr_short ( const void *pValue, unsigned nElem );
|
||||
@@ -72,6 +61,63 @@ private:
|
||||
typedef void ( comQueSend::*copyFunc_t ) (
|
||||
const void *pValue, unsigned nElem );
|
||||
static const copyFunc_t dbrCopyVector [39];
|
||||
|
||||
//
|
||||
// visual C++ version 6.0 does not allow out of
|
||||
// class member template function definition
|
||||
//
|
||||
template < class T >
|
||||
inline void copyIn ( const T *pVal, unsigned nElem )
|
||||
{
|
||||
unsigned nCopied;
|
||||
comBuf *pComBuf = this->bufs.last ();
|
||||
if ( pComBuf ) {
|
||||
nCopied = pComBuf->copyIn ( pVal, nElem );
|
||||
this->nBytesPending += nCopied * sizeof ( T );
|
||||
}
|
||||
else {
|
||||
nCopied = 0u;
|
||||
}
|
||||
while ( nElem > nCopied ) {
|
||||
comBuf *pComBuf = new ( std::nothrow ) comBuf;
|
||||
if ( ! pComBuf ) {
|
||||
this->wire.forcedShutdown ();
|
||||
throw std::bad_alloc ();
|
||||
}
|
||||
unsigned nNew = pComBuf->copyIn ( &pVal[nCopied], nElem - nCopied );
|
||||
nCopied += nNew;
|
||||
this->nBytesPending += nNew * sizeof ( T );
|
||||
this->bufs.add ( *pComBuf );
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// visual C++ version 6.0 does not allow out of
|
||||
// class member template function definition
|
||||
//
|
||||
template < class T >
|
||||
inline void copyIn ( const T &val )
|
||||
{
|
||||
comBuf *pComBuf = this->bufs.last ();
|
||||
if ( pComBuf ) {
|
||||
if ( pComBuf->copyIn ( &val, 1u ) >= 1u ) {
|
||||
this->nBytesPending += sizeof ( T );
|
||||
return;
|
||||
}
|
||||
}
|
||||
pComBuf = new ( std::nothrow ) comBuf;
|
||||
if ( ! pComBuf ) {
|
||||
this->wire.forcedShutdown ();
|
||||
throw std::bad_alloc ();
|
||||
}
|
||||
if ( pComBuf->copyIn ( &val, 1u ) == 0u ) {
|
||||
this->wire.forcedShutdown ();
|
||||
throw -1;
|
||||
}
|
||||
this->bufs.add ( *pComBuf );
|
||||
this->nBytesPending += sizeof ( T );
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
static const unsigned maxBytesPendingTCP = 0x4000;
|
||||
@@ -81,9 +127,21 @@ public:
|
||||
comQueRecv ();
|
||||
~comQueRecv ();
|
||||
unsigned occupiedBytes () const;
|
||||
bool copyOutBytes ( void *pBuf, unsigned nBytes );
|
||||
unsigned copyOutBytes ( void *pBuf, unsigned nBytes );
|
||||
unsigned removeBytes ( unsigned nBytes );
|
||||
void pushLastComBufReceived ( comBuf & );
|
||||
void clear ();
|
||||
epicsInt8 popInt8 ();
|
||||
epicsUInt8 popUInt8 ();
|
||||
epicsInt16 popInt16 ();
|
||||
epicsUInt16 popUInt16 ();
|
||||
epicsInt32 popInt32 ();
|
||||
epicsUInt32 popUInt32 ();
|
||||
epicsFloat32 popFloat32 ();
|
||||
epicsFloat64 popFloat64 ();
|
||||
void popString ( epicsOldString * );
|
||||
|
||||
class insufficentBytesAvailable {};
|
||||
private:
|
||||
tsDLList < comBuf > bufs;
|
||||
};
|
||||
@@ -93,6 +151,7 @@ public:
|
||||
tcpRecvWatchdog ( tcpiiu &, double periodIn, epicsTimerQueue & queueIn );
|
||||
virtual ~tcpRecvWatchdog ();
|
||||
void rescheduleRecvTimer ();
|
||||
void sendBacklogProgressNotify ();
|
||||
void messageArrivalNotify ();
|
||||
void beaconArrivalNotify ();
|
||||
void beaconAnomalyNotify ();
|
||||
@@ -105,7 +164,7 @@ private:
|
||||
tcpiiu &iiu;
|
||||
bool responsePending;
|
||||
bool beaconAnomaly;
|
||||
expireStatus expire ();
|
||||
expireStatus expire ( const epicsTime & currentTime );
|
||||
};
|
||||
|
||||
class tcpSendWatchdog : private epicsTimerNotify {
|
||||
@@ -118,19 +177,18 @@ private:
|
||||
const double period;
|
||||
epicsTimer &timer;
|
||||
tcpiiu &iiu;
|
||||
expireStatus expire ();
|
||||
expireStatus expire ( const epicsTime & currentTime );
|
||||
};
|
||||
|
||||
class hostNameCache : public ipAddrToAsciiAsynchronous {
|
||||
public:
|
||||
hostNameCache ( const osiSockAddr &addr, ipAddrToAsciiEngine &engine );
|
||||
~hostNameCache ();
|
||||
void destroy ();
|
||||
void ioCompletionNotify ( const char *pHostName );
|
||||
void hostName ( char *pBuf, unsigned bufLength ) const;
|
||||
void * operator new ( size_t size );
|
||||
void operator delete ( void *pCadaver, size_t size );
|
||||
protected:
|
||||
~hostNameCache ();
|
||||
private:
|
||||
bool ioComplete;
|
||||
char hostNameBuf [128];
|
||||
@@ -141,14 +199,25 @@ private:
|
||||
extern "C" void cacSendThreadTCP ( void *pParam );
|
||||
extern "C" void cacRecvThreadTCP ( void *pParam );
|
||||
|
||||
// a modified ca header with capacity for large arrays
|
||||
struct caHdrLargeArray {
|
||||
ca_uint32_t m_postsize; // size of message extension
|
||||
ca_uint32_t m_count; // operation data count
|
||||
ca_uint32_t m_cid; // channel identifier
|
||||
ca_uint32_t m_available; // protocol stub dependent
|
||||
ca_uint16_t m_dataType; // operation data type
|
||||
ca_uint16_t m_cmmd; // operation to be performed
|
||||
};
|
||||
|
||||
class tcpiiu :
|
||||
public netiiu, public tsDLNode < tcpiiu >,
|
||||
private wireSendAdapter, private wireRecvAdapter {
|
||||
public:
|
||||
tcpiiu ( cac &cac, double connectionTimeout, epicsTimerQueue &timerQueue );
|
||||
tcpiiu ( cac &cac, double connectionTimeout,
|
||||
epicsTimerQueue &timerQueue, const osiSockAddr &addrIn,
|
||||
unsigned minorVersion, class bhe &bhe,
|
||||
ipAddrToAsciiEngine &engineIn );
|
||||
~tcpiiu ();
|
||||
bool initiateConnect ( const osiSockAddr &addrIn, unsigned minorVersion,
|
||||
class bhe &bhe, ipAddrToAsciiEngine &engineIn );
|
||||
void connect ();
|
||||
void processIncoming ();
|
||||
void destroy ();
|
||||
@@ -157,7 +226,6 @@ public:
|
||||
void beaconAnomalyNotify ();
|
||||
void beaconArrivalNotify ();
|
||||
|
||||
bool fullyConstructed () const;
|
||||
void flushRequest ();
|
||||
bool flushBlockThreshold () const;
|
||||
void flushRequestIfAboveEarlyThreshold ();
|
||||
@@ -168,13 +236,14 @@ public:
|
||||
bool ca_v41_ok () const;
|
||||
bool ca_v42_ok () const;
|
||||
bool ca_v44_ok () const;
|
||||
bool ca_v49_ok () const;
|
||||
|
||||
void hostName ( char *pBuf, unsigned bufLength ) const;
|
||||
const char * pHostName () const; // deprecated - please do not use
|
||||
bool isVirtaulCircuit ( const char *pChannelName, const osiSockAddr &addr ) const;
|
||||
bool alive () const;
|
||||
double beaconPeriod () const;
|
||||
bhe * getBHE () const;
|
||||
bhe & getBHE () const;
|
||||
|
||||
SOCKET getSock() const;
|
||||
bool trueOnceOnly ();
|
||||
@@ -184,26 +253,29 @@ private:
|
||||
tcpSendWatchdog sendDog;
|
||||
comQueSend sendQue;
|
||||
comQueRecv recvQue;
|
||||
caHdrLargeArray curMsg;
|
||||
osiSockAddr addr;
|
||||
hostNameCache *pHostNameCache;
|
||||
caHdr curMsg;
|
||||
unsigned long curDataMax;
|
||||
class bhe *pBHE;
|
||||
arrayElementCount curDataMax;
|
||||
arrayElementCount curDataBytes;
|
||||
epics_auto_ptr < hostNameCache > pHostNameCache;
|
||||
class bhe & BHE;
|
||||
char *pCurData;
|
||||
unsigned minorProtocolVersion;
|
||||
iiu_conn_state state;
|
||||
epicsEventId sendThreadFlushSignal;
|
||||
epicsEventId recvThreadRingBufferSpaceAvailableSignal;
|
||||
epicsEventId sendThreadExitSignal;
|
||||
epicsEventId recvThreadExitSignal;
|
||||
epicsEventId flushBlockSignal;
|
||||
epicsEvent sendThreadFlushEvent;
|
||||
epicsEvent recvThreadRingBufferSpaceAvailableEvent;
|
||||
epicsEvent sendThreadExitEvent;
|
||||
epicsEvent recvThreadExitEvent;
|
||||
epicsEvent flushBlockEvent;
|
||||
SOCKET sock;
|
||||
unsigned contigRecvMsgCount;
|
||||
unsigned blockingForFlush;
|
||||
bool fullyConstructedFlag;
|
||||
unsigned socketLibrarySendBufferSize;
|
||||
unsigned unacknowledgedSendBytes;
|
||||
bool busyStateDetected; // only modified by the recv thread
|
||||
bool flowControlActive; // only modified by the send process thread
|
||||
bool echoRequestPending;
|
||||
bool oldMsgHeaderAvailable;
|
||||
bool msgHeaderAvailable;
|
||||
bool sockCloseCompleted;
|
||||
bool f_trueOnceOnly;
|
||||
@@ -235,38 +307,6 @@ private:
|
||||
bool flush (); // only to be called by the send thread
|
||||
};
|
||||
|
||||
inline bufferReservoir::~bufferReservoir ()
|
||||
{
|
||||
this->drain ();
|
||||
}
|
||||
|
||||
inline comBuf *bufferReservoir::fetchOneBuffer ()
|
||||
{
|
||||
return this->reservedBufs.get ();
|
||||
}
|
||||
|
||||
inline void bufferReservoir::addOneBuffer ()
|
||||
{
|
||||
comBuf *pBuf = new comBuf;
|
||||
if ( ! pBuf ) {
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
this->reservedBufs.add ( *pBuf );
|
||||
}
|
||||
|
||||
inline unsigned bufferReservoir::nBytes ()
|
||||
{
|
||||
return ( this->reservedBufs.count () * comBuf::capacityBytes () );
|
||||
}
|
||||
|
||||
inline void bufferReservoir::drain ()
|
||||
{
|
||||
comBuf *pBuf;
|
||||
while ( ( pBuf = this->reservedBufs.get () ) ) {
|
||||
pBuf->destroy ();
|
||||
}
|
||||
}
|
||||
|
||||
inline bool comQueSend::dbr_type_ok ( unsigned type )
|
||||
{
|
||||
if ( type >= ( sizeof ( this->dbrCopyVector ) / sizeof ( this->dbrCopyVector[0] ) ) ) {
|
||||
@@ -278,105 +318,24 @@ inline bool comQueSend::dbr_type_ok ( unsigned type )
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
// 1) 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).
|
||||
//
|
||||
// 2) Arguments here are a bit verbose until compilers all implement
|
||||
// member template functions.
|
||||
//
|
||||
|
||||
template < class T >
|
||||
inline void comQueSend_copyIn ( unsigned &nBytesPending,
|
||||
tsDLList < comBuf > &comBufList, bufferReservoir &reservoir,
|
||||
const T *pVal, unsigned nElem )
|
||||
{
|
||||
nBytesPending += sizeof ( T ) * nElem;
|
||||
|
||||
comBuf *pComBuf = comBufList.last ();
|
||||
if ( pComBuf ) {
|
||||
unsigned nCopied = pComBuf->copyIn ( pVal, nElem );
|
||||
if ( nElem > nCopied ) {
|
||||
comQueSend_copyInWithReservour ( comBufList, reservoir, &pVal[nCopied],
|
||||
nElem - nCopied );
|
||||
}
|
||||
}
|
||||
else {
|
||||
comQueSend_copyInWithReservour ( comBufList, reservoir, pVal, nElem );
|
||||
}
|
||||
}
|
||||
|
||||
template < class T >
|
||||
void comQueSend_copyInWithReservour (
|
||||
tsDLList < comBuf > &comBufList, bufferReservoir &reservoir,
|
||||
const T *pVal, unsigned nElem )
|
||||
{
|
||||
unsigned nCopied = 0u;
|
||||
while ( nElem > nCopied ) {
|
||||
comBuf *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 ( unsigned &nBytesPending,
|
||||
tsDLList < comBuf > &comBufList, bufferReservoir &reservoir,
|
||||
const T &val )
|
||||
{
|
||||
nBytesPending += sizeof ( T );
|
||||
|
||||
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 );
|
||||
}
|
||||
|
||||
inline void comQueSend::pushUInt16 ( const ca_uint16_t value )
|
||||
{
|
||||
comQueSend_copyIn ( this->nBytesPending,
|
||||
this->bufs, this->reservoir, value );
|
||||
this->copyIn ( value );
|
||||
}
|
||||
|
||||
inline void comQueSend::pushUInt32 ( const ca_uint32_t value )
|
||||
{
|
||||
comQueSend_copyIn ( this->nBytesPending,
|
||||
this->bufs, this->reservoir, value );
|
||||
this->copyIn ( value );
|
||||
}
|
||||
|
||||
inline void comQueSend::pushFloat32 ( const ca_float32_t value )
|
||||
{
|
||||
comQueSend_copyIn ( this->nBytesPending,
|
||||
this->bufs, this->reservoir, value );
|
||||
this->copyIn ( value );
|
||||
}
|
||||
|
||||
inline void comQueSend::pushString ( const char *pVal, unsigned nElem )
|
||||
inline void comQueSend::pushString ( const char *pVal, unsigned nChar )
|
||||
{
|
||||
comQueSend_copyIn ( this->nBytesPending,
|
||||
this->bufs, this->reservoir, pVal, nElem );
|
||||
this->copyIn ( pVal, nChar );
|
||||
}
|
||||
|
||||
// it is assumed that dbr_type_ok() was called prior to calling this routine
|
||||
@@ -415,19 +374,80 @@ inline comBuf * comQueSend::popNextComBufToSend ()
|
||||
return pBuf;
|
||||
}
|
||||
|
||||
inline bool tcpiiu::fullyConstructed () const
|
||||
|
||||
inline epicsInt8 comQueRecv::popInt8 ()
|
||||
{
|
||||
return this->fullyConstructedFlag;
|
||||
return static_cast < epicsInt8 > ( this->popUInt8() );
|
||||
}
|
||||
|
||||
inline epicsUInt16 comQueRecv::popUInt16 ()
|
||||
{
|
||||
epicsUInt16 tmp = this->popUInt8 ();
|
||||
tmp <<= 8u;
|
||||
tmp |= this->popUInt8 ();
|
||||
return tmp;
|
||||
}
|
||||
|
||||
inline epicsInt16 comQueRecv::popInt16 ()
|
||||
{
|
||||
epicsInt16 tmp = this->popInt8 ();
|
||||
tmp <<= 8u;
|
||||
tmp |= this->popInt8 ();
|
||||
return tmp;
|
||||
}
|
||||
|
||||
inline epicsUInt32 comQueRecv::popUInt32 ()
|
||||
{
|
||||
epicsUInt32 tmp = this->popUInt8 ();
|
||||
tmp <<= 24u;
|
||||
tmp |= this->popUInt8 () << 16u;
|
||||
tmp |= this->popUInt8 () << 8u;
|
||||
tmp |= this->popUInt8 ();
|
||||
return tmp;
|
||||
}
|
||||
|
||||
inline epicsInt32 comQueRecv::popInt32 ()
|
||||
{
|
||||
epicsInt32 tmp = this->popInt8 ();
|
||||
tmp <<= 24u;
|
||||
tmp |= this->popInt8 () << 16u;
|
||||
tmp |= this->popInt8 () << 8u;
|
||||
tmp |= this->popInt8 ();
|
||||
return tmp;
|
||||
}
|
||||
|
||||
inline epicsFloat32 comQueRecv::popFloat32 ()
|
||||
{
|
||||
epicsFloat32 tmp;
|
||||
epicsUInt8 wire[ sizeof ( tmp ) ];
|
||||
for ( unsigned i = 0u; i < sizeof ( tmp ); i++ ) {
|
||||
wire[i] = this->popUInt8 ();
|
||||
}
|
||||
osiConvertFromWireFormat ( tmp, wire );
|
||||
return tmp;
|
||||
}
|
||||
|
||||
inline epicsFloat64 comQueRecv::popFloat64 ()
|
||||
{
|
||||
epicsFloat64 tmp;
|
||||
epicsUInt8 wire[ sizeof ( tmp ) ];
|
||||
for ( unsigned i = 0u; i < sizeof ( tmp ); i++ ) {
|
||||
wire[i] = this->popUInt8 ();
|
||||
}
|
||||
osiConvertFromWireFormat ( tmp, wire );
|
||||
return tmp;
|
||||
}
|
||||
|
||||
inline void comQueRecv::popString ( epicsOldString *pStr )
|
||||
{
|
||||
for ( unsigned i = 0u; i < sizeof ( *pStr ); i++ ) {
|
||||
pStr[0][i] = this->popInt8 ();
|
||||
}
|
||||
}
|
||||
|
||||
inline void tcpiiu::hostName ( char *pBuf, unsigned bufLength ) const
|
||||
{
|
||||
if ( this->pHostNameCache ) {
|
||||
this->pHostNameCache->hostName ( pBuf, bufLength );
|
||||
}
|
||||
else {
|
||||
netiiu::hostName ( pBuf, bufLength );
|
||||
}
|
||||
this->pHostNameCache->hostName ( pBuf, bufLength );
|
||||
}
|
||||
|
||||
// deprecated - please dont use - this is _not_ thread safe
|
||||
@@ -440,17 +460,22 @@ inline const char * tcpiiu::pHostName () const
|
||||
|
||||
inline void tcpiiu::flushRequest ()
|
||||
{
|
||||
epicsEventSignal ( this->sendThreadFlushSignal );
|
||||
}
|
||||
|
||||
inline bool tcpiiu::ca_v44_ok () const
|
||||
{
|
||||
return CA_V44 ( CA_PROTOCOL_VERSION, this->minorProtocolVersion );
|
||||
this->sendThreadFlushEvent.signal ();
|
||||
}
|
||||
|
||||
inline bool tcpiiu::ca_v41_ok () const
|
||||
{
|
||||
return CA_V41 ( CA_PROTOCOL_VERSION, this->minorProtocolVersion );
|
||||
return CA_V41 ( this->minorProtocolVersion );
|
||||
}
|
||||
|
||||
inline bool tcpiiu::ca_v44_ok () const
|
||||
{
|
||||
return CA_V44 ( this->minorProtocolVersion );
|
||||
}
|
||||
|
||||
inline bool tcpiiu::ca_v49_ok () const
|
||||
{
|
||||
return CA_V49 ( this->minorProtocolVersion );
|
||||
}
|
||||
|
||||
inline bool tcpiiu::alive () const
|
||||
@@ -464,9 +489,9 @@ inline bool tcpiiu::alive () const
|
||||
}
|
||||
}
|
||||
|
||||
inline bhe * tcpiiu::getBHE () const
|
||||
inline bhe & tcpiiu::getBHE () const
|
||||
{
|
||||
return this->pBHE;
|
||||
return this->BHE;
|
||||
}
|
||||
|
||||
inline void tcpiiu::beaconAnomalyNotify ()
|
||||
|
||||
+713
-677
File diff suppressed because it is too large
Load Diff
+25
-22
@@ -48,24 +48,23 @@
|
||||
*
|
||||
* CA server TCP client task (one spawned for each client)
|
||||
*/
|
||||
void camsgtask (struct client *client)
|
||||
void camsgtask ( struct client *client )
|
||||
{
|
||||
int nchars;
|
||||
int status;
|
||||
int nchars;
|
||||
int status;
|
||||
|
||||
client->tid = epicsThreadGetIdSelf ();
|
||||
casAttachThreadToClient ( client );
|
||||
|
||||
taskwdInsert (epicsThreadGetIdSelf(), NULL, NULL);
|
||||
|
||||
while (TRUE) {
|
||||
while ( TRUE ) {
|
||||
client->recv.stk = 0;
|
||||
|
||||
nchars = recv (client->sock, &client->recv.buf[client->recv.cnt],
|
||||
(int)(sizeof(client->recv.buf)-client->recv.cnt), 0);
|
||||
if (nchars==0){
|
||||
if (CASDEBUG>0) {
|
||||
assert ( client->recv.maxstk >= client->recv.cnt );
|
||||
nchars = recv ( client->sock, &client->recv.buf[client->recv.cnt],
|
||||
(int) ( client->recv.maxstk - client->recv.cnt ), 0 );
|
||||
if ( nchars == 0 ){
|
||||
if ( CASDEBUG > 0 ) {
|
||||
errlogPrintf ( "CAS: nill message disconnect ( %u bytes request )\n",
|
||||
sizeof (client->recv.buf) - client->recv.cnt );
|
||||
sizeof ( client->recv.buf ) - client->recv.cnt );
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -75,19 +74,19 @@ void camsgtask (struct client *client)
|
||||
/*
|
||||
* normal conn lost conditions
|
||||
*/
|
||||
if ( (anerrno!=SOCK_ECONNABORTED&&
|
||||
anerrno!=SOCK_ECONNRESET&&
|
||||
anerrno!=SOCK_ETIMEDOUT)||
|
||||
CASDEBUG>2) {
|
||||
errlogPrintf ("CAS: client disconnect(errno=%d)\n", anerrno);
|
||||
if ( ( anerrno != SOCK_ECONNABORTED &&
|
||||
anerrno != SOCK_ECONNRESET &&
|
||||
anerrno != SOCK_ETIMEDOUT ) ||
|
||||
CASDEBUG > 2 ) {
|
||||
errlogPrintf ( "CAS: client disconnect(errno=%d)\n", anerrno );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
epicsTimeGetCurrent (&client->time_at_last_recv);
|
||||
client->recv.cnt += (unsigned long) nchars;
|
||||
epicsTimeGetCurrent ( &client->time_at_last_recv );
|
||||
client->recv.cnt += ( unsigned ) nchars;
|
||||
|
||||
status = camessage (client, &client->recv);
|
||||
status = camessage ( client );
|
||||
if (status == 0) {
|
||||
/*
|
||||
* if there is a partial message
|
||||
@@ -138,6 +137,10 @@ void camsgtask (struct client *client)
|
||||
cas_send_msg(client, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
destroy_client (client);
|
||||
|
||||
LOCK_CLIENTQ;
|
||||
ellDelete ( &clientQ, &client->node );
|
||||
UNLOCK_CLIENTQ;
|
||||
|
||||
destroy_tcp_client ( client );
|
||||
}
|
||||
|
||||
+133
-69
@@ -37,8 +37,10 @@
|
||||
#include "osiSock.h"
|
||||
#include "epicsTime.h"
|
||||
#include "errlog.h"
|
||||
#include "net_convert.h"
|
||||
|
||||
typedef unsigned long arrayElementCount;
|
||||
|
||||
#include "net_convert.h"
|
||||
#include "server.h"
|
||||
|
||||
/*
|
||||
@@ -46,65 +48,27 @@
|
||||
*
|
||||
* (channel access server send message)
|
||||
*/
|
||||
void cas_send_msg (struct client *pclient, int lock_needed)
|
||||
void cas_send_msg ( struct client *pclient, int lock_needed )
|
||||
{
|
||||
int status;
|
||||
|
||||
if (CASDEBUG>2 && pclient->send.stk) {
|
||||
errlogPrintf ("CAS: Sending a message of %d bytes\n", pclient->send.stk);
|
||||
if ( CASDEBUG > 2 && pclient->send.stk ) {
|
||||
errlogPrintf ( "CAS: Sending a message of %d bytes\n", pclient->send.stk );
|
||||
}
|
||||
|
||||
if (pclient->disconnect) {
|
||||
if (CASDEBUG>2) {
|
||||
errlogPrintf ("CAS: msg Discard for sock %d addr %x\n",
|
||||
pclient->sock, pclient->addr.sin_addr.s_addr);
|
||||
if ( pclient->disconnect ) {
|
||||
if ( CASDEBUG > 2 ) {
|
||||
errlogPrintf ( "CAS: msg Discard for sock %d addr %x\n",
|
||||
pclient->sock, pclient->addr.sin_addr.s_addr );
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if(lock_needed){
|
||||
SEND_LOCK(pclient);
|
||||
if ( lock_needed ) {
|
||||
SEND_LOCK ( pclient );
|
||||
}
|
||||
|
||||
if (pclient->send.stk) {
|
||||
#ifdef CONVERSION_REQUIRED
|
||||
/* Convert all caHdr into net format.
|
||||
* The remaining bytes must already be in
|
||||
* net format, because here we have no clue
|
||||
* how to convert them.
|
||||
*/
|
||||
char *buf;
|
||||
unsigned long msg_size, num_bytes;
|
||||
caHdr *mp;
|
||||
|
||||
|
||||
buf = (char *) pclient->send.buf;
|
||||
num_bytes = pclient->send.stk;
|
||||
|
||||
/* convert only if we have at least a complete caHdr */
|
||||
while (num_bytes >= sizeof(caHdr))
|
||||
{
|
||||
mp = (caHdr *) buf;
|
||||
|
||||
msg_size = sizeof (caHdr) + mp->m_postsize;
|
||||
|
||||
DLOG(3,"CAS: sending cmmd %d, postsize %d\n",
|
||||
mp->m_cmmd, (int)mp->m_postsize,
|
||||
0, 0, 0, 0);
|
||||
|
||||
/* convert the complete header into host format */
|
||||
mp->m_cmmd = htons (mp->m_cmmd);
|
||||
mp->m_postsize = htons (mp->m_postsize);
|
||||
mp->m_dataType = htons (mp->m_dataType);
|
||||
mp->m_count = htons (mp->m_count);
|
||||
mp->m_cid = htonl (mp->m_cid);
|
||||
mp->m_available = htonl (mp->m_available);
|
||||
|
||||
/* get next message: */
|
||||
buf += msg_size;
|
||||
num_bytes -= msg_size;
|
||||
}
|
||||
#endif
|
||||
if ( pclient->send.stk ) {
|
||||
|
||||
status = sendto (pclient->sock, pclient->send.buf, pclient->send.stk, 0,
|
||||
(struct sockaddr *)&pclient->addr, sizeof(pclient->addr));
|
||||
@@ -156,39 +120,52 @@ void cas_send_msg (struct client *pclient, int lock_needed)
|
||||
SEND_UNLOCK(pclient);
|
||||
}
|
||||
|
||||
DLOG(3, "------------------------------\n\n", 0,0,0,0,0,0);
|
||||
DLOG ( 3, ( "------------------------------\n\n" ) );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* cas_alloc_msg()
|
||||
* cas_copy_in_header()
|
||||
*
|
||||
* see also ALLOC_MSG()/END_MSG() in server.h
|
||||
*
|
||||
* (allocate space in the outgoing message buffer)
|
||||
* Allocate space in the outgoing message buffer and
|
||||
* copy in message header. Return pointer to message body.
|
||||
*
|
||||
* send lock must be on while in this routine
|
||||
*
|
||||
* returns 1) a valid ptr to msg buffer space
|
||||
* 2) NULL (msg will not fit)
|
||||
* Returns a valid ptr to message body or NULL if the msg
|
||||
* will not fit.
|
||||
*/
|
||||
caHdr *cas_alloc_msg (struct client *pclient, unsigned extsize)
|
||||
int cas_copy_in_header (
|
||||
struct client *pclient, ca_uint16_t response, ca_uint32_t payloadSize,
|
||||
ca_uint16_t dataType, ca_uint32_t nElem, ca_uint32_t cid,
|
||||
ca_uint32_t responseSpecific, void **ppPayload )
|
||||
{
|
||||
unsigned msgsize;
|
||||
unsigned msgSize;
|
||||
|
||||
extsize = CA_MESSAGE_ALIGN(extsize);
|
||||
|
||||
if ( extsize > UINT_MAX - sizeof(caHdr) ) {
|
||||
return NULL;
|
||||
}
|
||||
msgsize = extsize + sizeof(caHdr);
|
||||
if ( msgsize > pclient->send.maxstk ) {
|
||||
return NULL;
|
||||
if ( payloadSize > UINT_MAX - sizeof ( caHdr ) - 8u ) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if ( pclient->send.stk > pclient->send.maxstk - msgsize ) {
|
||||
payloadSize = CA_MESSAGE_ALIGN ( payloadSize );
|
||||
|
||||
msgSize = payloadSize + sizeof ( caHdr );
|
||||
if ( payloadSize >= 0xffff || nElem >= 0xffff ) {
|
||||
if ( ! CA_V49 ( pclient->minor_version_number ) ) {
|
||||
return FALSE;
|
||||
}
|
||||
msgSize += 2 * sizeof ( ca_uint32_t );
|
||||
}
|
||||
|
||||
if ( msgSize > pclient->send.maxstk ) {
|
||||
casExpandSendBuffer ( pclient, msgSize );
|
||||
if ( msgSize > pclient->send.maxstk ) {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if ( pclient->send.stk > pclient->send.maxstk - msgSize ) {
|
||||
if ( pclient->disconnect ) {
|
||||
pclient->send.stk = 0;
|
||||
}
|
||||
@@ -197,8 +174,95 @@ caHdr *cas_alloc_msg (struct client *pclient, unsigned extsize)
|
||||
}
|
||||
}
|
||||
|
||||
if ( payloadSize < 0xffff && nElem < 0xffff ) {
|
||||
caHdr *pMsg = ( caHdr * ) &pclient->send.buf[pclient->send.stk];
|
||||
pMsg->m_cmmd = htons ( response );
|
||||
pMsg->m_postsize = htons ( ( ( ca_uint16_t ) payloadSize ) );
|
||||
pMsg->m_dataType = htons ( dataType );
|
||||
pMsg->m_count = htons ( ( ( ca_uint16_t ) nElem ) );
|
||||
pMsg->m_cid = htonl ( cid );
|
||||
pMsg->m_available = htonl ( responseSpecific );
|
||||
if ( ppPayload ) {
|
||||
*ppPayload = ( void * ) ( pMsg + 1 );
|
||||
}
|
||||
}
|
||||
else {
|
||||
caHdr *pMsg = ( caHdr * ) &pclient->send.buf[pclient->send.stk];
|
||||
ca_uint32_t *pW32 = ( ca_uint32_t * ) ( pMsg + 1 );
|
||||
pMsg->m_cmmd = htons ( response );
|
||||
pMsg->m_postsize = htons ( 0xffff );
|
||||
pMsg->m_dataType = htons ( dataType );
|
||||
pMsg->m_count = htons ( 0u );
|
||||
pMsg->m_cid = htonl ( cid );
|
||||
pMsg->m_available = htonl ( responseSpecific );
|
||||
pW32[0] = htonl ( payloadSize );
|
||||
pW32[1] = htonl ( nElem );
|
||||
if ( ppPayload ) {
|
||||
*ppPayload = ( void * ) ( pW32 + 2 );
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void cas_set_header_cid ( struct client *pClient, ca_uint32_t cid )
|
||||
{
|
||||
caHdr *pMsg = ( caHdr * ) &pClient->send.buf[pClient->send.stk];
|
||||
pMsg->m_cid = htonl ( cid );
|
||||
}
|
||||
|
||||
void cas_commit_msg ( struct client *pClient, ca_uint32_t size )
|
||||
{
|
||||
caHdr * pMsg = ( caHdr * ) &pClient->send.buf[pClient->send.stk];
|
||||
size = CA_MESSAGE_ALIGN ( size );
|
||||
if ( pMsg->m_postsize == htons ( 0xffff ) ) {
|
||||
ca_uint32_t * pLW = ( ca_uint32_t * ) ( pMsg + 1 );
|
||||
assert ( size <= ntohl ( *pLW ) );
|
||||
pLW[0] = htonl ( size );
|
||||
size += sizeof ( caHdr ) + 2 * sizeof ( *pLW );
|
||||
}
|
||||
else {
|
||||
assert ( size <= ntohs ( pMsg->m_postsize ) );
|
||||
pMsg->m_postsize = htons ( (ca_uint16_t) size );
|
||||
size += sizeof ( caHdr );
|
||||
}
|
||||
pClient->send.stk += size;
|
||||
}
|
||||
|
||||
/*
|
||||
* this assumes that we have already checked to see
|
||||
* if sufficent bytes are available
|
||||
*/
|
||||
ca_uint16_t rsrvGetUInt16 ( struct message_buffer *recv )
|
||||
{
|
||||
ca_uint16_t tmp;
|
||||
/*
|
||||
* it fits END_MSG will push it on the stack
|
||||
* this assumes that we have already checked to see
|
||||
* if sufficent bytes are available
|
||||
*/
|
||||
return (caHdr *) &pclient->send.buf[pclient->send.stk];
|
||||
assert ( recv->cnt - recv->stk >= 2u );
|
||||
tmp = recv->buf[recv->stk++];
|
||||
tmp <<= 8u;
|
||||
tmp |= recv->buf[recv->stk++];
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/*
|
||||
* this assumes that we have already checked to see
|
||||
* if sufficent bytes are available
|
||||
*/
|
||||
ca_uint16_t rsrvGetUInt32 ( struct message_buffer *recv )
|
||||
{
|
||||
ca_uint16_t tmp;
|
||||
/*
|
||||
* this assumes that we have already checked to see
|
||||
* if sufficent bytes are available
|
||||
*/
|
||||
assert ( recv->cnt - recv->stk >= 4u );
|
||||
tmp = recv->buf[recv->stk++];
|
||||
tmp <<= 24u;
|
||||
tmp |= recv->buf[recv->stk++] << 16u;
|
||||
tmp |= recv->buf[recv->stk++] << 8u;
|
||||
tmp |= recv->buf[recv->stk++];
|
||||
return tmp;
|
||||
}
|
||||
|
||||
+366
-312
@@ -57,213 +57,6 @@
|
||||
#define DELETE_TASK(NAME)\
|
||||
if(threadNameToId(NAME)!=0)threadDestroy(threadNameToId(NAME));
|
||||
|
||||
/*
|
||||
* create_base_client ()
|
||||
*/
|
||||
struct client *create_base_client ()
|
||||
{
|
||||
struct client *client;
|
||||
|
||||
client = freeListMalloc (rsrvClientFreeList);
|
||||
if (!client) {
|
||||
epicsPrintf ("CAS: no space in pool for a new client\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* The following inits to zero done instead of a bfill since the send
|
||||
* and recv buffers are large and don't need initialization.
|
||||
*
|
||||
* memset(client, 0, sizeof(*client));
|
||||
*/
|
||||
|
||||
client->blockSem = epicsEventCreate(epicsEventEmpty);
|
||||
if(!client->blockSem){
|
||||
freeListFree(rsrvClientFreeList, client);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* user name initially unknown
|
||||
*/
|
||||
client->pUserName = malloc(1);
|
||||
if(!client->pUserName){
|
||||
epicsEventDestroy(client->blockSem);
|
||||
freeListFree(rsrvClientFreeList, client);
|
||||
return NULL;
|
||||
}
|
||||
client->pUserName[0] = '\0';
|
||||
|
||||
/*
|
||||
* host name initially unknown
|
||||
*/
|
||||
client->pHostName = malloc(1);
|
||||
if(!client->pHostName){
|
||||
epicsEventDestroy(client->blockSem);
|
||||
free(client->pUserName);
|
||||
freeListFree(rsrvClientFreeList, client);
|
||||
return NULL;
|
||||
}
|
||||
client->pHostName[0] = '\0';
|
||||
|
||||
ellInit(&client->addrq);
|
||||
ellInit(&client->putNotifyQue);
|
||||
memset((char *)&client->addr, 0, sizeof(client->addr));
|
||||
client->tid = 0;
|
||||
client->sock = INVALID_SOCKET;
|
||||
client->send.stk = 0ul;
|
||||
client->send.cnt = 0ul;
|
||||
client->recv.stk = 0ul;
|
||||
client->recv.cnt = 0ul;
|
||||
client->evuser = NULL;
|
||||
client->disconnect = FALSE; /* for TCP only */
|
||||
epicsTimeGetCurrent(&client->time_at_last_send);
|
||||
epicsTimeGetCurrent(&client->time_at_last_recv);
|
||||
client->proto = IPPROTO_UDP;
|
||||
client->minor_version_number = CA_UKN_MINOR_VERSION;
|
||||
|
||||
client->send.maxstk = MAX_UDP_SEND;
|
||||
|
||||
client->lock = epicsMutexMustCreate();
|
||||
client->putNotifyLock = epicsMutexMustCreate();
|
||||
client->addrqLock = epicsMutexMustCreate();
|
||||
client->eventqLock = epicsMutexMustCreate();
|
||||
|
||||
client->recv.maxstk = MAX_UDP_RECV;
|
||||
return client;
|
||||
}
|
||||
|
||||
/*
|
||||
* create_client ()
|
||||
*/
|
||||
struct client *create_client (SOCKET sock)
|
||||
{
|
||||
int status;
|
||||
struct client *client;
|
||||
int true = TRUE;
|
||||
osiSocklen_t addrSize;
|
||||
unsigned priorityOfEvents;
|
||||
|
||||
/*
|
||||
* see TCP(4P) this seems to make unsolicited single events much
|
||||
* faster. I take care of queue up as load increases.
|
||||
*/
|
||||
status = setsockopt (sock, IPPROTO_TCP, TCP_NODELAY,
|
||||
(char *)&true, sizeof(true));
|
||||
if (status < 0) {
|
||||
errlogPrintf ("CAS: TCP_NODELAY option set failed\n");
|
||||
socket_close (sock);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* turn on KEEPALIVE so if the client crashes
|
||||
* this task will find out and exit
|
||||
*/
|
||||
status = setsockopt (sock, SOL_SOCKET, SO_KEEPALIVE,
|
||||
(char *)&true, sizeof(true));
|
||||
if (status < 0) {
|
||||
errlogPrintf ("CAS: SO_KEEPALIVE option set failed\n");
|
||||
socket_close (sock);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* some concern that vxWorks will run out of mBuf's
|
||||
* if this change is made
|
||||
*
|
||||
* joh 11-10-98
|
||||
*/
|
||||
#if 0
|
||||
/*
|
||||
* set TCP buffer sizes to be synergistic
|
||||
* with CA internal buffering
|
||||
*/
|
||||
i = MAX_MSG_SIZE;
|
||||
status = setsockopt (sock, SOL_SOCKET, SO_SNDBUF, (char *)&i, sizeof(i));
|
||||
if (status < 0) {
|
||||
errlogPrintf ("CAS: SO_SNDBUF set failed\n");
|
||||
socket_close (sock);
|
||||
return NULL;
|
||||
}
|
||||
i = MAX_MSG_SIZE;
|
||||
status = setsockopt (sock, SOL_SOCKET, SO_RCVBUF, (char *)&i, sizeof(i));
|
||||
if (status < 0) {
|
||||
errlogPrintf ("CAS: SO_RCVBUF set failed\n");
|
||||
socket_close (sock);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
client = (struct client *) create_base_client ();
|
||||
if (!client) {
|
||||
errlogPrintf("CAS: client init failed\n");
|
||||
socket_close (sock);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
client->proto = IPPROTO_TCP;
|
||||
client->send.maxstk = MAX_TCP;
|
||||
client->recv.maxstk = MAX_TCP;
|
||||
client->sock = sock;
|
||||
|
||||
addrSize = sizeof (client->addr);
|
||||
status = getpeername (sock, (struct sockaddr *)&client->addr,
|
||||
&addrSize);
|
||||
if (status < 0) {
|
||||
epicsPrintf ("CAS: peer address fetch failed\n");
|
||||
destroy_client (client);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
client->evuser = (struct event_user *) db_init_events();
|
||||
if (!client->evuser) {
|
||||
errlogPrintf ("CAS: unable to init the event facility\n");
|
||||
destroy_client (client);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
status = db_add_extra_labor_event (client->evuser, write_notify_reply, client);
|
||||
if (status != DB_EVENT_OK) {
|
||||
errlogPrintf("CAS: unable to setup the event facility\n");
|
||||
destroy_client (client);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
{
|
||||
unsigned priorityOfSelf = epicsThreadGetPrioritySelf ();
|
||||
epicsThreadBooleanStatus tbs;
|
||||
|
||||
tbs = epicsThreadLowestPriorityLevelAbove ( priorityOfSelf, &priorityOfEvents );
|
||||
if ( tbs != epicsThreadBooleanStatusSuccess ) {
|
||||
priorityOfEvents = priorityOfSelf;
|
||||
}
|
||||
}
|
||||
|
||||
status = db_start_events ( client->evuser, "CAS-event",
|
||||
NULL, NULL, priorityOfEvents );
|
||||
if (status != DB_EVENT_OK) {
|
||||
errlogPrintf("CAS: unable to start the event facility\n");
|
||||
destroy_client (client);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
client->recv.cnt = 0ul;
|
||||
|
||||
if (CASDEBUG>0) {
|
||||
char buf[64];
|
||||
ipAddrToDottedIP (&client->addr, buf, sizeof(buf));
|
||||
errlogPrintf ("CAS: conn req from %s\n", buf);
|
||||
}
|
||||
|
||||
LOCK_CLIENTQ;
|
||||
ellAdd (&clientQ, &client->node);
|
||||
UNLOCK_CLIENTQ;
|
||||
|
||||
return client;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* req_server()
|
||||
@@ -404,18 +197,23 @@ LOCAL int req_server (void)
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
struct client *pClient;
|
||||
unsigned priorityOfClient;
|
||||
epicsThreadId id;
|
||||
struct client *pClient;
|
||||
|
||||
pClient = create_client (clientSock);
|
||||
if (!pClient) {
|
||||
pClient = create_tcp_client ( clientSock );
|
||||
if ( ! pClient ) {
|
||||
errlogPrintf ( "CAS: unable to create new client because \"%s\"\n",
|
||||
strerror (errno) );
|
||||
epicsThreadSleep(15.0);
|
||||
strerror ( errno ) );
|
||||
epicsThreadSleep ( 15.0 );
|
||||
continue;
|
||||
}
|
||||
|
||||
LOCK_CLIENTQ;
|
||||
ellAdd ( &clientQ, &pClient->node );
|
||||
UNLOCK_CLIENTQ;
|
||||
|
||||
|
||||
/*
|
||||
* go up two levels in priority so that the event task is above the
|
||||
* task waiting in accept ()
|
||||
@@ -433,10 +231,10 @@ LOCAL int req_server (void)
|
||||
}
|
||||
|
||||
id = epicsThreadCreate ( "CAS-client", priorityOfClient,
|
||||
epicsThreadGetStackSize (epicsThreadStackBig),
|
||||
(EPICSTHREADFUNC)camsgtask, (void *)pClient );
|
||||
if (id==0) {
|
||||
destroy_client ( pClient );
|
||||
epicsThreadGetStackSize ( epicsThreadStackBig ),
|
||||
( EPICSTHREADFUNC ) camsgtask, pClient );
|
||||
if ( id == 0 ) {
|
||||
destroy_tcp_client ( pClient );
|
||||
errlogPrintf ( "CAS: task creation for new client failed\n" );
|
||||
epicsThreadSleep ( 15.0 );
|
||||
continue;
|
||||
@@ -451,21 +249,50 @@ LOCAL int req_server (void)
|
||||
epicsShareFunc int epicsShareAPI rsrv_init (void)
|
||||
{
|
||||
epicsThreadId tid;
|
||||
long maxBytesAsALong;
|
||||
long status;
|
||||
|
||||
clientQlock = epicsMutexMustCreate();
|
||||
|
||||
ellInit (&clientQ);
|
||||
freeListInitPvt (&rsrvClientFreeList, sizeof(struct client), 8);
|
||||
freeListInitPvt (&rsrvChanFreeList, sizeof(struct channel_in_use), 512);
|
||||
freeListInitPvt (&rsrvEventFreeList, sizeof(struct event_ext), 512);
|
||||
ellInit (&beaconAddrList);
|
||||
ellInit ( &clientQ );
|
||||
freeListInitPvt ( &rsrvClientFreeList, sizeof(struct client), 8 );
|
||||
freeListInitPvt ( &rsrvChanFreeList, sizeof(struct channel_in_use), 512 );
|
||||
freeListInitPvt ( &rsrvEventFreeList, sizeof(struct event_ext), 512 );
|
||||
freeListInitPvt ( &rsrvSmallBufFreeListTCP, MAX_TCP, 16 );
|
||||
|
||||
status = envGetLongConfigParam ( &EPICS_CA_MAX_ARRAY_BYTES, &maxBytesAsALong );
|
||||
if ( status || maxBytesAsALong < 0 ) {
|
||||
errlogPrintf ( "cas: EPICS_CA_MAX_ARRAY_BYTES was not a positive integer\n" );
|
||||
rsrvSizeofLargeBufTCP = MAX_TCP;
|
||||
}
|
||||
else {
|
||||
/* allow room for the protocol header so that they get the array size they requested */
|
||||
static const unsigned headerSize = sizeof ( caHdr ) + 2 * sizeof ( ca_uint32_t );
|
||||
ca_uint32_t maxBytes = ( unsigned ) maxBytesAsALong;
|
||||
if ( maxBytes < 0xffffffff - headerSize ) {
|
||||
maxBytes += headerSize;
|
||||
}
|
||||
else {
|
||||
maxBytes = 0xffffffff;
|
||||
}
|
||||
if ( maxBytes < MAX_TCP ) {
|
||||
errlogPrintf ( "cas: EPICS_CA_MAX_ARRAY_BYTES was rounded up to %u\n", MAX_TCP );
|
||||
rsrvSizeofLargeBufTCP = MAX_TCP;
|
||||
}
|
||||
else {
|
||||
rsrvSizeofLargeBufTCP = maxBytes;
|
||||
}
|
||||
}
|
||||
freeListInitPvt ( &rsrvLargeBufFreeListTCP, rsrvSizeofLargeBufTCP, 1 );
|
||||
|
||||
ellInit ( &beaconAddrList );
|
||||
prsrv_cast_client = NULL;
|
||||
pCaBucket = NULL;
|
||||
|
||||
tid = epicsThreadCreate ("CAS-TCP",
|
||||
tid = epicsThreadCreate ( "CAS-TCP",
|
||||
epicsThreadPriorityChannelAccessServer,
|
||||
epicsThreadGetStackSize(epicsThreadStackMedium),
|
||||
(EPICSTHREADFUNC)req_server,0);
|
||||
(EPICSTHREADFUNC)req_server, 0);
|
||||
if ( tid == 0 ) {
|
||||
epicsPrintf ( "CAS: unable to start connection request thread\n" );
|
||||
}
|
||||
@@ -483,9 +310,9 @@ LOCAL void log_one_client (struct client *client, unsigned level)
|
||||
char *pproto;
|
||||
double send_delay;
|
||||
double recv_delay;
|
||||
unsigned long bytes_reserved;
|
||||
unsigned bytes_reserved;
|
||||
char *state[] = {"up", "down"};
|
||||
epicsTimeStamp current;
|
||||
epicsTimeStamp current;
|
||||
char clientHostName[256];
|
||||
|
||||
ipAddrToDottedIP (&client->addr, clientHostName, sizeof(clientHostName));
|
||||
@@ -504,12 +331,11 @@ LOCAL void log_one_client (struct client *client, unsigned level)
|
||||
send_delay = epicsTimeDiffInSeconds(¤t,&client->time_at_last_send);
|
||||
recv_delay = epicsTimeDiffInSeconds(¤t,&client->time_at_last_recv);
|
||||
|
||||
printf( "%s(%s): User=\"%s\", V%d.%u, Channel Count=%d\n",
|
||||
printf( "%s(%s): User=\"%s\", V%s, Channel Count=%d\n",
|
||||
clientHostName,
|
||||
client->pHostName,
|
||||
client->pUserName,
|
||||
CA_PROTOCOL_VERSION,
|
||||
client->minor_version_number,
|
||||
client->pHostName ? client->pHostName : "",
|
||||
client->pUserName ? client->pUserName : "",
|
||||
CA_VERSION_STRING ( client->minor_version_number ),
|
||||
ellCount(&client->addrq));
|
||||
if (level>=1) {
|
||||
printf ("\tTask Id=%p, Protocol=%3s, Socket FD=%d\n", client->tid,
|
||||
@@ -587,11 +413,11 @@ void epicsShareAPI casr (unsigned level)
|
||||
return;
|
||||
}
|
||||
|
||||
printf ("Channel Access Server V%d.%d\n",
|
||||
CA_PROTOCOL_VERSION, CA_MINOR_VERSION);
|
||||
printf ("Channel Access Server V%s\n",
|
||||
CA_VERSION_STRING ( CA_MINOR_PROTOCOL_REVISION ) );
|
||||
|
||||
LOCK_CLIENTQ
|
||||
client = (struct client *) ellNext (&clientQ);
|
||||
client = (struct client *) ellNext ( &clientQ );
|
||||
if (!client) {
|
||||
printf("No clients connected.\n");
|
||||
}
|
||||
@@ -636,72 +462,118 @@ void epicsShareAPI casr (unsigned level)
|
||||
/*
|
||||
* destroy_client ()
|
||||
*/
|
||||
void destroy_client (struct client *client)
|
||||
void destroy_client ( struct client *client )
|
||||
{
|
||||
if ( ! client ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( client->tid != 0 ) {
|
||||
taskwdRemove ( client->tid );
|
||||
}
|
||||
|
||||
|
||||
if ( client->sock != INVALID_SOCKET ) {
|
||||
if ( socket_close (client->sock) < 0) {
|
||||
errlogPrintf( "CAS: Unable to close socket\n" );
|
||||
}
|
||||
}
|
||||
|
||||
if ( client->proto == IPPROTO_TCP ) {
|
||||
if ( client->send.type == mbtSmallTCP ) {
|
||||
if ( client->send.buf ) {
|
||||
freeListFree ( rsrvSmallBufFreeListTCP, client->send.buf );
|
||||
}
|
||||
if ( client->recv.buf ) {
|
||||
freeListFree ( rsrvSmallBufFreeListTCP, client->recv.buf );
|
||||
}
|
||||
}
|
||||
else if ( client->send.type == mbtLargeTCP ) {
|
||||
if ( client->send.buf ) {
|
||||
freeListFree ( rsrvLargeBufFreeListTCP, client->send.buf );
|
||||
}
|
||||
if ( client->recv.buf ) {
|
||||
freeListFree ( rsrvLargeBufFreeListTCP, client->recv.buf );
|
||||
}
|
||||
}
|
||||
else {
|
||||
errlogPrintf ( "Currupt buffer type code during cleanup?\n" );
|
||||
}
|
||||
}
|
||||
else if ( client->proto == IPPROTO_UDP ) {
|
||||
if ( client->send.buf ) {
|
||||
free ( client->send.buf );
|
||||
}
|
||||
if ( client->recv.buf ) {
|
||||
free ( client->recv.buf );
|
||||
}
|
||||
}
|
||||
|
||||
epicsMutexDestroy ( client->eventqLock );
|
||||
|
||||
epicsMutexDestroy ( client->addrqLock );
|
||||
|
||||
epicsMutexDestroy ( client->putNotifyLock );
|
||||
|
||||
epicsMutexDestroy ( client->lock );
|
||||
|
||||
epicsEventDestroy ( client->blockSem );
|
||||
|
||||
if ( client->pUserName ) {
|
||||
free ( client->pUserName );
|
||||
}
|
||||
|
||||
if ( client->pHostName ) {
|
||||
free ( client->pHostName );
|
||||
}
|
||||
|
||||
freeListFree ( rsrvClientFreeList, client );
|
||||
}
|
||||
|
||||
void destroy_tcp_client ( struct client *client )
|
||||
{
|
||||
struct event_ext *pevext;
|
||||
struct channel_in_use *pciu;
|
||||
int status;
|
||||
|
||||
if (!client) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (client->proto != IPPROTO_TCP) {
|
||||
errlogPrintf ("CAS: non TCP client delete ignored\n");
|
||||
return;
|
||||
if ( CASDEBUG > 0 ) {
|
||||
errlogPrintf ( "CAS: Connection %d Terminated\n", client->sock );
|
||||
}
|
||||
|
||||
LOCK_CLIENTQ;
|
||||
ellDelete (&clientQ, &client->node);
|
||||
UNLOCK_CLIENTQ;
|
||||
|
||||
if (CASDEBUG>0) {
|
||||
errlogPrintf ("CAS: Connection %d Terminated\n", client->sock);
|
||||
if ( client->evuser ) {
|
||||
db_event_flow_ctrl_mode_off ( client->evuser );
|
||||
}
|
||||
|
||||
/*
|
||||
* exit flow control so the event system will
|
||||
* shutdown correctly
|
||||
*/
|
||||
db_event_flow_ctrl_mode_off (client->evuser);
|
||||
|
||||
/*
|
||||
* Server task deleted first since close() is not reentrant
|
||||
*/
|
||||
if ( client->tid != 0 ) {
|
||||
taskwdRemove (client->tid);
|
||||
}
|
||||
|
||||
while(TRUE){
|
||||
epicsMutexMustLock (client->addrqLock);
|
||||
pciu = (struct channel_in_use *) ellGet(&client->addrq);
|
||||
epicsMutexUnlock (client->addrqLock);
|
||||
if (!pciu) {
|
||||
while ( TRUE ){
|
||||
epicsMutexMustLock ( client->addrqLock );
|
||||
pciu = (struct channel_in_use *) ellGet ( &client->addrq );
|
||||
epicsMutexUnlock ( client->addrqLock );
|
||||
if ( ! pciu ) {
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* put notify in progress needs to be deleted
|
||||
*/
|
||||
if (pciu->pPutNotify) {
|
||||
if (pciu->pPutNotify->busy) {
|
||||
dbNotifyCancel (&pciu->pPutNotify->dbPutNotify);
|
||||
if ( pciu->pPutNotify ) {
|
||||
if ( pciu->pPutNotify->busy ) {
|
||||
dbNotifyCancel ( &pciu->pPutNotify->dbPutNotify );
|
||||
}
|
||||
}
|
||||
|
||||
while (TRUE){
|
||||
while ( TRUE ) {
|
||||
/*
|
||||
* AS state change could be using this list
|
||||
*/
|
||||
epicsMutexMustLock (client->eventqLock);
|
||||
epicsMutexMustLock ( client->eventqLock );
|
||||
|
||||
pevext = (struct event_ext *) ellGet(&pciu->eventq);
|
||||
epicsMutexUnlock (client->eventqLock);
|
||||
if(!pevext){
|
||||
pevext = (struct event_ext *) ellGet ( &pciu->eventq );
|
||||
epicsMutexUnlock ( client->eventqLock );
|
||||
if ( ! pevext ) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (pevext->pdbev) {
|
||||
if ( pevext->pdbev ) {
|
||||
db_cancel_event (pevext->pdbev);
|
||||
}
|
||||
freeListFree (rsrvEventFreeList, pevext);
|
||||
@@ -712,60 +584,242 @@ void destroy_client (struct client *client)
|
||||
free(pciu->pPutNotify);
|
||||
}
|
||||
LOCK_CLIENTQ;
|
||||
status = bucketRemoveItemUnsignedId (
|
||||
pCaBucket,
|
||||
&pciu->sid);
|
||||
status = bucketRemoveItemUnsignedId ( pCaBucket, &pciu->sid);
|
||||
UNLOCK_CLIENTQ;
|
||||
if(status != S_bucket_success){
|
||||
errPrintf (
|
||||
status,
|
||||
__FILE__,
|
||||
__LINE__,
|
||||
"Bad id=%d at close",
|
||||
pciu->sid);
|
||||
if ( status != S_bucket_success ) {
|
||||
errPrintf ( status, __FILE__, __LINE__,
|
||||
"Bad id=%d at close", pciu->sid);
|
||||
}
|
||||
status = asRemoveClient(&pciu->asClientPVT);
|
||||
if(status!=0 && status != S_asLib_asNotActive){
|
||||
printf("And the status is %x \n", status);
|
||||
errPrintf(status, __FILE__, __LINE__, "asRemoveClient");
|
||||
if ( status && status != S_asLib_asNotActive ) {
|
||||
printf ( "bad asRemoveClient() status was %x \n", status );
|
||||
errPrintf ( status, __FILE__, __LINE__, "asRemoveClient" );
|
||||
}
|
||||
|
||||
/*
|
||||
* place per channel block onto the
|
||||
* free list
|
||||
*/
|
||||
freeListFree (rsrvChanFreeList, pciu);
|
||||
freeListFree ( rsrvChanFreeList, pciu );
|
||||
}
|
||||
|
||||
if ( client->evuser ) {
|
||||
db_close_events (client->evuser);
|
||||
}
|
||||
|
||||
if (client->sock!=INVALID_SOCKET) {
|
||||
if ( socket_close (client->sock) < 0) {
|
||||
errlogPrintf("CAS: Unable to close socket\n");
|
||||
destroy_client ( client );
|
||||
}
|
||||
|
||||
/*
|
||||
* create_client ()
|
||||
*/
|
||||
struct client * create_client ( SOCKET sock, int proto )
|
||||
{
|
||||
struct client *client;
|
||||
|
||||
client = freeListCalloc ( rsrvClientFreeList );
|
||||
if ( ! client ) {
|
||||
epicsPrintf ("CAS: no space in pool for a new client\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
client->sock = sock;
|
||||
client->proto = proto;
|
||||
|
||||
client->blockSem = epicsEventCreate ( epicsEventEmpty );
|
||||
client->lock = epicsMutexCreate();
|
||||
client->putNotifyLock = epicsMutexCreate();
|
||||
client->addrqLock = epicsMutexCreate();
|
||||
client->eventqLock = epicsMutexCreate();
|
||||
if ( ! client->blockSem || ! client->lock || ! client->putNotifyLock ||
|
||||
! client->addrqLock || ! client->eventqLock ) {
|
||||
destroy_client ( client );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
client->pUserName = NULL;
|
||||
client->pHostName = NULL;
|
||||
ellInit ( &client->addrq );
|
||||
ellInit ( &client->putNotifyQue );
|
||||
memset ( (char *)&client->addr, 0, sizeof (client->addr) );
|
||||
client->tid = 0;
|
||||
|
||||
if ( proto == IPPROTO_TCP ) {
|
||||
client->send.buf = (char *) freeListCalloc ( rsrvSmallBufFreeListTCP );
|
||||
client->send.maxstk = MAX_TCP;
|
||||
client->send.type = mbtSmallTCP;
|
||||
client->recv.buf = (char *) freeListCalloc ( rsrvSmallBufFreeListTCP );
|
||||
client->recv.maxstk = MAX_TCP;
|
||||
client->recv.type = mbtSmallTCP;
|
||||
}
|
||||
else if ( proto == IPPROTO_UDP ) {
|
||||
client->send.buf = malloc ( MAX_UDP_SEND );
|
||||
client->send.maxstk = MAX_UDP_SEND;
|
||||
client->send.type = mbtUDP;
|
||||
client->recv.buf = malloc ( MAX_UDP_RECV );
|
||||
client->recv.maxstk = MAX_UDP_RECV;
|
||||
client->recv.type = mbtUDP;
|
||||
}
|
||||
if ( ! client->send.buf || ! client->recv.buf ) {
|
||||
destroy_client ( client );
|
||||
return NULL;
|
||||
}
|
||||
client->send.stk = 0u;
|
||||
client->send.cnt = 0u;
|
||||
client->recv.stk = 0u;
|
||||
client->recv.cnt = 0u;
|
||||
client->evuser = NULL;
|
||||
client->disconnect = FALSE;
|
||||
epicsTimeGetCurrent ( &client->time_at_last_send );
|
||||
epicsTimeGetCurrent ( &client->time_at_last_recv );
|
||||
client->minor_version_number = CA_UKN_MINOR_VERSION;
|
||||
client->recvBytesToDrain = 0u;
|
||||
|
||||
return client;
|
||||
}
|
||||
|
||||
void casAttachThreadToClient ( struct client *pClient )
|
||||
{
|
||||
pClient->tid = epicsThreadGetIdSelf ();
|
||||
taskwdInsert ( pClient->tid, NULL, NULL );
|
||||
}
|
||||
|
||||
void casExpandSendBuffer ( struct client *pClient, ca_uint32_t size )
|
||||
{
|
||||
if ( pClient->send.type == mbtSmallTCP && rsrvSizeofLargeBufTCP > MAX_TCP ) {
|
||||
char *pNewBuf = ( char * ) freeListCalloc ( rsrvLargeBufFreeListTCP );
|
||||
memcpy ( pNewBuf, pClient->send.buf, pClient->send.stk );
|
||||
pClient->send.buf = pNewBuf;
|
||||
pClient->send.maxstk = rsrvSizeofLargeBufTCP;
|
||||
pClient->send.type = mbtLargeTCP;
|
||||
}
|
||||
}
|
||||
|
||||
void casExpandRecvBuffer ( struct client *pClient, ca_uint32_t size )
|
||||
{
|
||||
if ( pClient->recv.type == mbtSmallTCP && rsrvSizeofLargeBufTCP > MAX_TCP ) {
|
||||
char *pNewBuf = ( char * ) freeListCalloc ( rsrvLargeBufFreeListTCP );
|
||||
assert ( pClient->recv.cnt >= pClient->recv.stk );
|
||||
memcpy ( pNewBuf, &pClient->recv.buf[pClient->recv.stk], pClient->recv.cnt - pClient->recv.stk );
|
||||
pClient->recv.buf = pNewBuf;
|
||||
pClient->recv.cnt = pClient->recv.cnt - pClient->recv.stk;
|
||||
pClient->recv.stk = 0u;
|
||||
pClient->recv.maxstk = rsrvSizeofLargeBufTCP;
|
||||
pClient->recv.type = mbtLargeTCP;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* create_tcp_client ()
|
||||
*/
|
||||
struct client *create_tcp_client ( SOCKET sock )
|
||||
{
|
||||
int status;
|
||||
struct client *client;
|
||||
int true = TRUE;
|
||||
osiSocklen_t addrSize;
|
||||
unsigned priorityOfEvents;
|
||||
|
||||
client = create_client ( sock, IPPROTO_TCP );
|
||||
if ( ! client ) {
|
||||
errlogPrintf ("CAS: no space in pool for a new TCP client\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* see TCP(4P) this seems to make unsolicited single events much
|
||||
* faster. I take care of queue up as load increases.
|
||||
*/
|
||||
status = setsockopt ( sock, IPPROTO_TCP, TCP_NODELAY,
|
||||
(char *) &true, sizeof (true) );
|
||||
if (status < 0) {
|
||||
errlogPrintf ( "CAS: TCP_NODELAY option set failed\n" );
|
||||
destroy_client ( client );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* turn on KEEPALIVE so if the client crashes
|
||||
* this task will find out and exit
|
||||
*/
|
||||
status = setsockopt ( sock, SOL_SOCKET, SO_KEEPALIVE,
|
||||
(char *) &true, sizeof (true) );
|
||||
if ( status < 0 ) {
|
||||
errlogPrintf ( "CAS: SO_KEEPALIVE option set failed\n" );
|
||||
destroy_client ( client );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* some concern that vxWorks will run out of mBuf's
|
||||
* if this change is made
|
||||
*
|
||||
* joh 11-10-98
|
||||
*/
|
||||
#if 0
|
||||
/*
|
||||
* set TCP buffer sizes to be synergistic
|
||||
* with CA internal buffering
|
||||
*/
|
||||
i = MAX_MSG_SIZE;
|
||||
status = setsockopt ( sock, SOL_SOCKET, SO_SNDBUF, (char *) &i, sizeof (i) );
|
||||
if (status < 0) {
|
||||
errlogPrintf ( "CAS: SO_SNDBUF set failed\n" );
|
||||
destroy_client ( client );
|
||||
return NULL;
|
||||
}
|
||||
i = MAX_MSG_SIZE;
|
||||
status = setsockopt ( sock, SOL_SOCKET, SO_RCVBUF, (char *) &i, sizeof (i) );
|
||||
if (status < 0) {
|
||||
errlogPrintf ( "CAS: SO_RCVBUF set failed\n" );
|
||||
destroy_client ( client );
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
addrSize = sizeof ( client->addr );
|
||||
status = getpeername ( sock, (struct sockaddr *)&client->addr,
|
||||
&addrSize );
|
||||
if ( status < 0 ) {
|
||||
epicsPrintf ("CAS: peer address fetch failed\n");
|
||||
destroy_tcp_client (client);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
client->evuser = (struct event_user *) db_init_events ();
|
||||
if ( ! client->evuser ) {
|
||||
errlogPrintf ("CAS: unable to init the event facility\n");
|
||||
destroy_tcp_client (client);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
status = db_add_extra_labor_event (client->evuser, write_notify_reply, client);
|
||||
if (status != DB_EVENT_OK) {
|
||||
errlogPrintf("CAS: unable to setup the event facility\n");
|
||||
destroy_tcp_client (client);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
{
|
||||
unsigned priorityOfSelf = epicsThreadGetPrioritySelf ();
|
||||
epicsThreadBooleanStatus tbs;
|
||||
|
||||
tbs = epicsThreadLowestPriorityLevelAbove ( priorityOfSelf, &priorityOfEvents );
|
||||
if ( tbs != epicsThreadBooleanStatusSuccess ) {
|
||||
priorityOfEvents = priorityOfSelf;
|
||||
}
|
||||
}
|
||||
|
||||
epicsMutexDestroy (client->eventqLock);
|
||||
|
||||
epicsMutexDestroy (client->addrqLock);
|
||||
|
||||
epicsMutexDestroy (client->putNotifyLock);
|
||||
|
||||
epicsMutexDestroy (client->lock);
|
||||
|
||||
epicsEventDestroy (client->blockSem);
|
||||
|
||||
if (client->pUserName) {
|
||||
free (client->pUserName);
|
||||
status = db_start_events ( client->evuser, "CAS-event",
|
||||
NULL, NULL, priorityOfEvents );
|
||||
if (status != DB_EVENT_OK) {
|
||||
errlogPrintf("CAS: unable to start the event facility\n");
|
||||
destroy_tcp_client (client);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (client->pHostName) {
|
||||
free (client->pHostName);
|
||||
if ( CASDEBUG > 0 ) {
|
||||
char buf[64];
|
||||
ipAddrToDottedIP ( &client->addr, buf, sizeof(buf) );
|
||||
errlogPrintf ( "CAS: conn req from %s\n", buf );
|
||||
}
|
||||
|
||||
client->minor_version_number = CA_UKN_MINOR_VERSION;
|
||||
|
||||
freeListFree (rsrvClientFreeList, client);
|
||||
return client;
|
||||
}
|
||||
|
||||
|
||||
+10
-12
@@ -60,7 +60,7 @@
|
||||
|
||||
#include "server.h"
|
||||
|
||||
#define TIMEOUT 60.0 /* sec */
|
||||
#define TIMEOUT 60.0 /* sec */
|
||||
|
||||
/*
|
||||
* clean_addrq
|
||||
@@ -233,34 +233,33 @@ int cast_server(void)
|
||||
* possible
|
||||
*
|
||||
*/
|
||||
while (TRUE) {
|
||||
prsrv_cast_client = create_base_client ();
|
||||
if (prsrv_cast_client) {
|
||||
while ( TRUE ) {
|
||||
prsrv_cast_client = create_client ( IOC_cast_sock, IPPROTO_UDP );
|
||||
if ( prsrv_cast_client ) {
|
||||
break;
|
||||
}
|
||||
epicsThreadSleep(300.0);
|
||||
}
|
||||
|
||||
prsrv_cast_client->sock = IOC_cast_sock;
|
||||
prsrv_cast_client->tid = epicsThreadGetIdSelf ();
|
||||
casAttachThreadToClient ( prsrv_cast_client );
|
||||
|
||||
while (TRUE) {
|
||||
status = recvfrom (
|
||||
IOC_cast_sock,
|
||||
prsrv_cast_client->recv.buf,
|
||||
sizeof(prsrv_cast_client->recv.buf),
|
||||
prsrv_cast_client->recv.maxstk,
|
||||
0,
|
||||
(struct sockaddr *)&new_recv_addr,
|
||||
&recv_addr_size);
|
||||
if (status<0) {
|
||||
epicsPrintf ("CAS: UDP recv error (errno=%s)\n",
|
||||
SOCKERRSTR(SOCKERRNO));
|
||||
epicsThreadSleep(1.0);
|
||||
epicsThreadSleep(1.0);
|
||||
}
|
||||
else {
|
||||
prsrv_cast_client->recv.cnt = (unsigned long) status;
|
||||
prsrv_cast_client->recv.cnt = (unsigned) status;
|
||||
prsrv_cast_client->recv.stk = 0ul;
|
||||
epicsTimeGetCurrent(&prsrv_cast_client->time_at_last_recv);
|
||||
epicsTimeGetCurrent(&prsrv_cast_client->time_at_last_recv);
|
||||
|
||||
/*
|
||||
* If we are talking to a new client flush to the old one
|
||||
@@ -292,8 +291,7 @@ int cast_server(void)
|
||||
if (CASDEBUG>2)
|
||||
count = ellCount (&prsrv_cast_client->addrq);
|
||||
|
||||
status = camessage(
|
||||
prsrv_cast_client,&prsrv_cast_client->recv);
|
||||
status = camessage ( prsrv_cast_client );
|
||||
if(status == RSRV_OK){
|
||||
if(prsrv_cast_client->recv.cnt !=
|
||||
prsrv_cast_client->recv.stk){
|
||||
|
||||
+57
-64
@@ -41,6 +41,7 @@
|
||||
#include "asLib.h"
|
||||
#include "dbAddr.h"
|
||||
#include "dbNotify.h"
|
||||
#define CA_MINOR_PROTOCOL_REVISION 9
|
||||
#include "caProto.h"
|
||||
#include "ellLib.h"
|
||||
#include "epicsTime.h"
|
||||
@@ -51,47 +52,38 @@
|
||||
|
||||
#define LOCAL static
|
||||
|
||||
/* a modified ca header with capacity for large arrays */
|
||||
typedef struct caHdrLargeArray {
|
||||
ca_uint32_t m_postsize; /* size of message extension */
|
||||
ca_uint32_t m_count; /* operation data count */
|
||||
ca_uint32_t m_cid; /* channel identifier */
|
||||
ca_uint32_t m_available; /* protocol stub dependent */
|
||||
ca_uint16_t m_dataType; /* operation data type */
|
||||
ca_uint16_t m_cmmd; /* operation to be performed */
|
||||
}caHdrLargeArray;
|
||||
|
||||
/*
|
||||
* !! buf must be the first item in this structure !!
|
||||
* This guarantees that buf will have 8 byte natural
|
||||
* alignment
|
||||
*
|
||||
* Conversions:
|
||||
* The contents of message_buffer has to be converted
|
||||
* from network to host format and vice versa.
|
||||
* For efficiency reasons, the caHdr structure that's common
|
||||
* to all messages is converted only once:
|
||||
* 1) from net to host just after receiving it in camessage()
|
||||
* 2) from host to net in cas_send_msg()
|
||||
*
|
||||
* The remaining message_buffer content, however, is always
|
||||
* in net format!
|
||||
*
|
||||
* The terminating unsigned long pad0 field is there to force the
|
||||
* The terminating unsigned pad0 field is there to force the
|
||||
* length of the message_buffer to be a multiple of 8 bytes.
|
||||
* This is due to the sequential placing of two message_buffer
|
||||
* structures (trans, rec) within the client structure.
|
||||
* Eight-byte alignment is required by the Sparc 5 and other RISC
|
||||
* processors.
|
||||
*
|
||||
* CAVEAT: This assumes the following:
|
||||
* o an array of MAX_MSG_SIZE chars takes a multiple of 8 bytes.
|
||||
* o four unsigned longs also take up a multiple of 8 bytes
|
||||
* (usually 2).
|
||||
* NOTE:
|
||||
* o we should solve the above message alignment problems by
|
||||
* allocating the message buffers
|
||||
*
|
||||
*/
|
||||
enum messageBufferType { mbtUDP, mbtSmallTCP, mbtLargeTCP };
|
||||
struct message_buffer {
|
||||
char buf[MAX_MSG_SIZE];
|
||||
unsigned long stk;
|
||||
unsigned long maxstk;
|
||||
unsigned long cnt;
|
||||
unsigned long pad0; /* force 8 byte alignement */
|
||||
char *buf;
|
||||
unsigned stk;
|
||||
unsigned maxstk;
|
||||
unsigned cnt;
|
||||
enum messageBufferType type;
|
||||
};
|
||||
|
||||
struct client {
|
||||
typedef struct client {
|
||||
ELLNODE node;
|
||||
struct message_buffer send;
|
||||
struct message_buffer recv;
|
||||
@@ -102,8 +94,8 @@ struct client {
|
||||
ELLLIST addrq;
|
||||
ELLLIST putNotifyQue;
|
||||
struct sockaddr_in addr;
|
||||
epicsTimeStamp time_at_last_send;
|
||||
epicsTimeStamp time_at_last_recv;
|
||||
epicsTimeStamp time_at_last_send;
|
||||
epicsTimeStamp time_at_last_recv;
|
||||
void *evuser;
|
||||
char *pUserName;
|
||||
char *pHostName;
|
||||
@@ -112,8 +104,9 @@ struct client {
|
||||
int proto;
|
||||
epicsThreadId tid;
|
||||
unsigned minor_version_number;
|
||||
unsigned recvBytesToDrain;
|
||||
char disconnect; /* disconnect detected */
|
||||
};
|
||||
} client;
|
||||
|
||||
|
||||
/*
|
||||
@@ -122,8 +115,8 @@ struct client {
|
||||
typedef struct rsrv_put_notify {
|
||||
ELLNODE node;
|
||||
PUTNOTIFY dbPutNotify;
|
||||
caHdr msg;
|
||||
unsigned long valueSize; /* size of block pointed to by dbPutNotify */
|
||||
caHdrLargeArray msg;
|
||||
unsigned valueSize; /* size of block pointed to by dbPutNotify */
|
||||
int busy; /* put notify in progress */
|
||||
} RSRVPUTNOTIFY;
|
||||
|
||||
@@ -139,7 +132,7 @@ struct channel_in_use {
|
||||
RSRVPUTNOTIFY *pPutNotify; /* potential active put notify */
|
||||
const unsigned cid; /* client id */
|
||||
const unsigned sid; /* server id */
|
||||
epicsTimeStamp time_at_creation; /* for UDP timeout */
|
||||
epicsTimeStamp time_at_creation; /* for UDP timeout */
|
||||
struct dbAddr addr;
|
||||
ASCLIENTPVT asClientPVT;
|
||||
};
|
||||
@@ -151,7 +144,7 @@ struct channel_in_use {
|
||||
*/
|
||||
struct event_ext {
|
||||
ELLNODE node;
|
||||
caHdr msg;
|
||||
caHdrLargeArray msg;
|
||||
struct channel_in_use *pciu;
|
||||
struct event_block *pdbev; /* ptr to db event block */
|
||||
unsigned size; /* for speed */
|
||||
@@ -173,13 +166,10 @@ struct event_ext {
|
||||
* for debug-level dependent messages:
|
||||
*/
|
||||
#ifdef DEBUG
|
||||
# define DLOG(level, fmt, a1, a2, a3, a4, a5, a6) \
|
||||
if (CASDEBUG > level) errlogPrintf (fmt, a1, a2, a3, a4, a5, a6)
|
||||
# define DBLOCK(level, code) \
|
||||
if (CASDEBUG > level) { code; }
|
||||
# define DLOG(LEVEL,ARGSINPAREN) \
|
||||
if (CASDEBUG > LEVEL) errlogPrintf ARGSINPAREN
|
||||
#else
|
||||
# define DLOG(level, fmt, a1, a2, a3, a4, a5, a6)
|
||||
# define DBLOCK(level, code)
|
||||
# define DLOG(LEVEL,ARGSINPAREN)
|
||||
#endif
|
||||
|
||||
GLBLTYPE int CASDEBUG;
|
||||
@@ -194,6 +184,9 @@ GLBLTYPE BUCKET *pCaBucket;
|
||||
GLBLTYPE void *rsrvClientFreeList;
|
||||
GLBLTYPE void *rsrvChanFreeList;
|
||||
GLBLTYPE void *rsrvEventFreeList;
|
||||
GLBLTYPE void *rsrvSmallBufFreeListTCP;
|
||||
GLBLTYPE void *rsrvLargeBufFreeListTCP;
|
||||
GLBLTYPE unsigned rsrvSizeofLargeBufTCP;
|
||||
|
||||
#define CAS_HASH_TABLE_SIZE 4096
|
||||
|
||||
@@ -202,37 +195,37 @@ GLBLTYPE int casSufficentSpaceInPool;
|
||||
#define SEND_LOCK(CLIENT) epicsMutexMustLock((CLIENT)->lock)
|
||||
#define SEND_UNLOCK(CLIENT) epicsMutexUnlock((CLIENT)->lock)
|
||||
|
||||
#define EXTMSGPTR(CLIENT)\
|
||||
((caHdr *) &(CLIENT)->send.buf[(CLIENT)->send.stk])
|
||||
|
||||
/*
|
||||
* ALLOC_MSG get a ptr to space in the buffer
|
||||
* END_MSG push a message onto the buffer stack
|
||||
*
|
||||
*/
|
||||
#define ALLOC_MSG(CLIENT, EXTSIZE) cas_alloc_msg (CLIENT, EXTSIZE)
|
||||
|
||||
#define END_MSG(CLIENT)\
|
||||
EXTMSGPTR(CLIENT)->m_postsize = CA_MESSAGE_ALIGN(EXTMSGPTR(CLIENT)->m_postsize),\
|
||||
(CLIENT)->send.stk += sizeof(caHdr) + EXTMSGPTR(CLIENT)->m_postsize
|
||||
|
||||
#define LOCK_CLIENTQ epicsMutexMustLock (clientQlock);
|
||||
#define UNLOCK_CLIENTQ epicsMutexUnlock (clientQlock);
|
||||
|
||||
void camsgtask (struct client *client);
|
||||
void cas_send_msg (struct client *pclient, int lock_needed);
|
||||
caHdr *cas_alloc_msg (struct client *pclient, unsigned extsize);
|
||||
int rsrv_online_notify_task (void);
|
||||
void cac_send_heartbeat (void);
|
||||
int cast_server (void);
|
||||
struct client *create_base_client ();
|
||||
int camessage (struct client *client,
|
||||
struct message_buffer *recv);
|
||||
void cas_send_heartbeat (struct client *pc);
|
||||
void write_notify_reply (void *pArg);
|
||||
int rsrvCheckPut (const struct channel_in_use *pciu);
|
||||
struct client *create_client (SOCKET sock);
|
||||
void destroy_client (struct client *client);
|
||||
struct client *create_client ();
|
||||
void destroy_client ( struct client * );
|
||||
struct client *create_tcp_client ( SOCKET sock );
|
||||
void destroy_tcp_client ( struct client * );
|
||||
void casAttachThreadToClient ( struct client * );
|
||||
int camessage ( struct client *client );
|
||||
void write_notify_reply ( void *pArg );
|
||||
int rsrvCheckPut ( const struct channel_in_use *pciu );
|
||||
|
||||
/*
|
||||
* inclming protocol maintetnance
|
||||
*/
|
||||
void casExpandRecvBuffer ( struct client *pClient, ca_uint32_t size );
|
||||
|
||||
/*
|
||||
* outgoing protocol maintenance
|
||||
*/
|
||||
void casExpandSendBuffer ( struct client *pClient, ca_uint32_t size );
|
||||
int cas_copy_in_header (
|
||||
struct client *pClient, ca_uint16_t response, ca_uint32_t payloadSize,
|
||||
ca_uint16_t dataType, ca_uint32_t nElem, ca_uint32_t cid,
|
||||
ca_uint32_t responseSpecific, void **pPayload );
|
||||
void cas_set_header_cid ( struct client *pClient, ca_uint32_t );
|
||||
void cas_commit_msg ( struct client *pClient, ca_uint32_t size );
|
||||
|
||||
/*
|
||||
* !!KLUDGE!!
|
||||
|
||||
Reference in New Issue
Block a user