Stage 1 reorganization
Directory moves. src/RTEMS/ => src/libCom/RTEMS/ src/as/ => src/ioc/as/ src/bpt/ => src/ioc/bpt/ src/ca/ => src/ca/client/ src/cap5/ => src/ca/client/perl/ src/cas/ => src/ca/legacy/pcas/ src/catools/ => src/ca/client/tools/ src/db/ => src/ioc/db/ src/dbStatic/ => src/ioc/dbStatic/ src/dbtools/ => src/ioc/dbtemplate/ src/dev/softDev/ => src/std/dev/ src/dev/testDev/ => src/std/test/ src/excas/ => src/ca/legacy/pcas/ex/ src/gdd/ => src/ca/legacy/gdd/ src/makeBaseApp/ => src/template/base/ src/makeBaseExt/ => src/template/ext/ src/misc/ => src/ioc/misc/ src/rec/ => src/std/rec/ src/registry/ => src/ioc/registry/ src/rsrv/ => src/ioc/rsrv/ src/softIoc/ => src/std/softIoc/ src/toolsComm/ => src/libCom/tools/
This commit is contained in:
committed by
Andrew Johnson
parent
4a18db9f99
commit
2a36a3906d
365
src/ca/client/bhe.cpp
Normal file
365
src/ca/client/bhe.cpp
Normal file
@@ -0,0 +1,365 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* Copyright (c) 2002 The Regents of the University of California, as
|
||||
* Operator of Los Alamos National Laboratory.
|
||||
* EPICS BASE Versions 3.13.7
|
||||
* and higher are distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
|
||||
/*
|
||||
*
|
||||
* L O S A L A M O S
|
||||
* Los Alamos National Laboratory
|
||||
* Los Alamos, New Mexico 87545
|
||||
*
|
||||
* Copyright, 1986, The Regents of the University of California.
|
||||
*
|
||||
* Author: Jeff Hill
|
||||
*/
|
||||
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include <limits.h>
|
||||
#include <float.h>
|
||||
|
||||
#define epicsAssertAuthor "Jeff Hill johill@lanl.gov"
|
||||
|
||||
#include "errlog.h"
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include "iocinf.h"
|
||||
#include "virtualCircuit.h"
|
||||
#include "bhe.h"
|
||||
|
||||
/*
|
||||
* set average to -1.0 so that when the next beacon
|
||||
* occurs we can distinguish between:
|
||||
* o new server
|
||||
* o existing server's beacon we are seeing
|
||||
* for the first time shortly after program
|
||||
* start up
|
||||
*
|
||||
* if creating this in response to a search reply
|
||||
* and not in response to a beacon then
|
||||
* we set the beacon time stamp to
|
||||
* zero (so we can correctly compute the period
|
||||
* between the 1st and 2nd beacons)
|
||||
*/
|
||||
bhe::bhe ( epicsMutex & mutexIn, const epicsTime & initialTimeStamp,
|
||||
unsigned initialBeaconNumber, const inetAddrID & addr ) :
|
||||
inetAddrID ( addr ), timeStamp ( initialTimeStamp ), averagePeriod ( - DBL_MAX ),
|
||||
mutex ( mutexIn ), pIIU ( 0 ), lastBeaconNumber ( initialBeaconNumber )
|
||||
{
|
||||
# ifdef DEBUG
|
||||
{
|
||||
char name[64];
|
||||
addr.name ( name, sizeof ( name ) );
|
||||
::printf ( "created beacon entry for %s\n", name );
|
||||
}
|
||||
# endif
|
||||
}
|
||||
|
||||
bhe::~bhe ()
|
||||
{
|
||||
}
|
||||
|
||||
void bhe::beaconAnomalyNotify ( epicsGuard < epicsMutex > & guard )
|
||||
{
|
||||
guard.assertIdenticalMutex ( this->mutex );
|
||||
if ( this->pIIU ) {
|
||||
this->pIIU->beaconAnomalyNotify ( guard );
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
void bhe::logBeacon ( const char * pDiagnostic,
|
||||
const double & currentPeriod,
|
||||
const epicsTime & currentTime )
|
||||
{
|
||||
if ( this->pIIU ) {
|
||||
char name[64];
|
||||
this->name ( name, sizeof ( name ) );
|
||||
char date[64];
|
||||
currentTime.strftime ( date, sizeof ( date ),
|
||||
"%a %b %d %Y %H:%M:%S.%f");
|
||||
::printf ( "%s cp=%g ap=%g %s %s\n",
|
||||
pDiagnostic, currentPeriod,
|
||||
this->averagePeriod, name, date );
|
||||
}
|
||||
}
|
||||
#else
|
||||
inline void bhe::logBeacon ( const char * /* pDiagnostic */,
|
||||
const double & /* currentPeriod */,
|
||||
const epicsTime & /* currentTime */ )
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
void bhe::logBeaconDiscard ( unsigned beaconAdvance,
|
||||
const epicsTime & currentTime )
|
||||
{
|
||||
if ( this->pIIU ) {
|
||||
char name[64];
|
||||
this->name ( name, sizeof ( name ) );
|
||||
char date[64];
|
||||
currentTime.strftime ( date, sizeof ( date ),
|
||||
"%a %b %d %Y %H:%M:%S.%f");
|
||||
::printf ( "bb %u %s %s\n",
|
||||
beaconAdvance, name, date );
|
||||
}
|
||||
}
|
||||
#else
|
||||
void bhe::logBeaconDiscard ( unsigned /* beaconAdvance */,
|
||||
const epicsTime & /* currentTime */ )
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* update beacon period
|
||||
*
|
||||
* updates beacon period, and looks for beacon anomalies
|
||||
*/
|
||||
bool bhe::updatePeriod (
|
||||
epicsGuard < epicsMutex > & guard, const epicsTime & programBeginTime,
|
||||
const epicsTime & currentTime, ca_uint32_t beaconNumber,
|
||||
unsigned protocolRevision )
|
||||
{
|
||||
guard.assertIdenticalMutex ( this->mutex );
|
||||
|
||||
//
|
||||
// this block is enetered if the beacon was created as a side effect of
|
||||
// creating a connection and so we dont yet know the first beacon time
|
||||
// and sequence number
|
||||
//
|
||||
if ( this->timeStamp == epicsTime () ) {
|
||||
if ( CA_V410 ( protocolRevision ) ) {
|
||||
this->lastBeaconNumber = beaconNumber;
|
||||
}
|
||||
|
||||
this->beaconAnomalyNotify ( guard );
|
||||
|
||||
/*
|
||||
* this is the 1st beacon seen - the beacon time stamp
|
||||
* was not initialized during BHE create because
|
||||
* a TCP/IP connection created the beacon.
|
||||
* (nothing to do but set the beacon time stamp and return)
|
||||
*/
|
||||
this->timeStamp = currentTime;
|
||||
|
||||
logBeacon ( "fb", - DBL_MAX, currentTime );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// 1) detect beacon duplications due to redundant routes
|
||||
// 2) detect lost beacons due to input queue overrun or damage
|
||||
if ( CA_V410 ( protocolRevision ) ) {
|
||||
unsigned beaconSeqAdvance;
|
||||
if ( beaconNumber >= this->lastBeaconNumber ) {
|
||||
beaconSeqAdvance = beaconNumber - this->lastBeaconNumber;
|
||||
}
|
||||
else {
|
||||
beaconSeqAdvance = ( ca_uint32_max - this->lastBeaconNumber ) + beaconNumber;
|
||||
}
|
||||
this->lastBeaconNumber = beaconNumber;
|
||||
|
||||
// throw out sequence numbers just prior to, or the same as, the last one received
|
||||
// (this situation is probably caused by a temporary duplicate route )
|
||||
if ( beaconSeqAdvance == 0 || beaconSeqAdvance > ca_uint32_max - 256 ) {
|
||||
logBeaconDiscard ( beaconSeqAdvance, currentTime );
|
||||
return false;
|
||||
}
|
||||
|
||||
// throw out sequence numbers that jump forward by only a few numbers
|
||||
// (this situation is probably caused by a duplicate route
|
||||
// or a beacon due to input queue overun)
|
||||
if ( beaconSeqAdvance > 1 && beaconSeqAdvance < 4 ) {
|
||||
logBeaconDiscard ( beaconSeqAdvance, currentTime );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// compute the beacon period (if we have seen at least two beacons)
|
||||
bool netChange = false;
|
||||
double currentPeriod = currentTime - this->timeStamp;
|
||||
|
||||
if ( this->averagePeriod < 0.0 ) {
|
||||
double totalRunningTime;
|
||||
|
||||
this->beaconAnomalyNotify ( guard );
|
||||
|
||||
/*
|
||||
* this is the 2nd beacon seen. We cant tell about
|
||||
* the change in period at this point so we just
|
||||
* initialize the average period and return.
|
||||
*/
|
||||
this->averagePeriod = currentPeriod;
|
||||
|
||||
logBeacon ( "fp", currentPeriod, currentTime );
|
||||
|
||||
|
||||
/*
|
||||
* ignore beacons seen for the first time shortly after
|
||||
* init, but do not ignore beacons arriving with a short
|
||||
* period because the IOC was rebooted soon after the
|
||||
* client starts up.
|
||||
*/
|
||||
totalRunningTime = this->timeStamp - programBeginTime;
|
||||
if ( currentPeriod <= totalRunningTime ) {
|
||||
netChange = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
/*
|
||||
* Is this an IOC seen because of a restored
|
||||
* network segment?
|
||||
*
|
||||
* It may be possible to get false triggers here
|
||||
* if the client is busy, but this does not cause
|
||||
* problems because the echo response will tell us
|
||||
* that the server is available
|
||||
*/
|
||||
if ( currentPeriod >= this->averagePeriod * 1.25 ) {
|
||||
|
||||
/*
|
||||
* trigger on any missing beacon
|
||||
* if connected to this server
|
||||
*/
|
||||
this->beaconAnomalyNotify ( guard );
|
||||
|
||||
if ( currentPeriod >= this->averagePeriod * 3.25 ) {
|
||||
/*
|
||||
* trigger on any 3 contiguous missing beacons
|
||||
* if not connected to this server
|
||||
*/
|
||||
netChange = true;
|
||||
}
|
||||
logBeacon ( "bah", currentPeriod, currentTime );
|
||||
}
|
||||
|
||||
/*
|
||||
* Is this an IOC seen because of an IOC reboot
|
||||
* (beacon come at a higher rate just after the
|
||||
* IOC reboots). Lower tolarance here because we
|
||||
* dont have to worry about lost beacons.
|
||||
*
|
||||
* It may be possible to get false triggers here
|
||||
* if the client is busy, but this does not cause
|
||||
* problems because the echo response will tell us
|
||||
* that the server is available
|
||||
*/
|
||||
else if ( currentPeriod <= this->averagePeriod * 0.80 ) {
|
||||
this->beaconAnomalyNotify ( guard );
|
||||
netChange = true;
|
||||
logBeacon ( "bal", currentPeriod, currentTime );
|
||||
}
|
||||
else if ( this->pIIU ) {
|
||||
// update state of health for active virtual circuits
|
||||
// if the beacon looks ok
|
||||
this->pIIU->beaconArrivalNotify ( guard );
|
||||
logBeacon ( "vb", currentPeriod, currentTime );
|
||||
}
|
||||
|
||||
// update a running average period
|
||||
this->averagePeriod = currentPeriod * 0.125 +
|
||||
this->averagePeriod * 0.875;
|
||||
}
|
||||
|
||||
this->timeStamp = currentTime;
|
||||
|
||||
return netChange;
|
||||
}
|
||||
|
||||
void bhe::show ( unsigned level ) const
|
||||
{
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
this->show ( guard, level );
|
||||
}
|
||||
|
||||
void bhe::show ( epicsGuard < epicsMutex > &, unsigned level ) const
|
||||
{
|
||||
char host [64];
|
||||
this->name ( host, sizeof ( host ) );
|
||||
if ( this->averagePeriod == -DBL_MAX ) {
|
||||
::printf ( "CA beacon hash entry for %s <no period estimate>\n",
|
||||
host );
|
||||
}
|
||||
else {
|
||||
::printf ( "CA beacon hash entry for %s with period estimate %f\n",
|
||||
host, this->averagePeriod );
|
||||
}
|
||||
if ( level > 0u ) {
|
||||
char date[64];
|
||||
this->timeStamp.strftime ( date, sizeof ( date ), "%a %b %d %Y %H:%M:%S");
|
||||
::printf ( "\tbeacon number %u, on %s\n",
|
||||
this->lastBeaconNumber, date );
|
||||
}
|
||||
}
|
||||
|
||||
double bhe::period ( epicsGuard < epicsMutex > & guard ) const
|
||||
{
|
||||
guard.assertIdenticalMutex ( this->mutex );
|
||||
return this->averagePeriod;
|
||||
}
|
||||
|
||||
epicsTime bhe::updateTime ( epicsGuard < epicsMutex > & guard ) const
|
||||
{
|
||||
guard.assertIdenticalMutex ( this->mutex );
|
||||
return this->timeStamp;
|
||||
}
|
||||
|
||||
void bhe::registerIIU (
|
||||
epicsGuard < epicsMutex > & guard, tcpiiu & iiu )
|
||||
{
|
||||
guard.assertIdenticalMutex ( this->mutex );
|
||||
this->pIIU = & iiu;
|
||||
}
|
||||
|
||||
void bhe::unregisterIIU (
|
||||
epicsGuard < epicsMutex > & guard, tcpiiu & iiu )
|
||||
{
|
||||
guard.assertIdenticalMutex ( this->mutex );
|
||||
if ( this->pIIU == & iiu ) {
|
||||
this->pIIU = 0;
|
||||
this->timeStamp = epicsTime();
|
||||
this->averagePeriod = - DBL_MAX;
|
||||
logBeacon ( "ui", this->averagePeriod, epicsTime::getCurrent () );
|
||||
}
|
||||
}
|
||||
|
||||
void * bhe::operator new ( size_t ) // X aCC 361
|
||||
{
|
||||
// The HPUX compiler seems to require this even though no code
|
||||
// calls it directly
|
||||
throw std::logic_error ( "why is the compiler calling private operator new" );
|
||||
}
|
||||
|
||||
void bhe::operator delete ( void * )
|
||||
{
|
||||
// Visual C++ .net appears to require operator delete if
|
||||
// placement operator delete is defined? I smell a ms rat
|
||||
// because if I declare placement new and delete, but
|
||||
// comment out the placement delete definition there are
|
||||
// no undefined symbols.
|
||||
errlogPrintf ( "%s:%d this compiler is confused about placement delete - memory was probably leaked",
|
||||
__FILE__, __LINE__ );
|
||||
}
|
||||
|
||||
void * bheFreeStore::allocate ( size_t size )
|
||||
{
|
||||
return freeList.allocate ( size );
|
||||
}
|
||||
|
||||
void bheFreeStore::release ( void * pCadaver )
|
||||
{
|
||||
freeList.release ( pCadaver );
|
||||
}
|
||||
|
||||
bheMemoryManager::~bheMemoryManager () {}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user