/* * $Id$ * * Author Jeffrey O. Hill * johill@lanl.gov * 505 665 1831 * * Experimental Physics and Industrial Control System (EPICS) * * Copyright 1991, the Regents of the University of California, * and the University of Chicago Board of Governors. * * This software was produced under U.S. Government contracts: * (W-7405-ENG-36) at the Los Alamos National Laboratory, * and (W-31-109-ENG-38) at Argonne National Laboratory. * * Initial development by: * The Controls and Automation Group (AT-8) * Ground Test Accelerator * Accelerator Technology Division * Los Alamos National Laboratory * * Co-developed with * The Controls and Computing Group * Accelerator Systems Division * Advanced Photon Source * Argonne National Laboratory * * * History * $Log$ * Revision 1.8 1997/06/13 09:15:51 jhill * connect proto changes * * Revision 1.7 1997/04/10 19:33:53 jhill * API changes * * Revision 1.6 1996/11/02 00:53:54 jhill * many improvements * * Revision 1.5 1996/09/16 18:23:56 jhill * vxWorks port changes * * Revision 1.4 1996/09/04 20:12:04 jhill * added arg to serverToolDebugFunc() * * Revision 1.3 1996/08/13 22:56:12 jhill * added init for mutex class * * Revision 1.2 1996/08/05 19:25:17 jhill * removed unused code * * Revision 1.1.1.1 1996/06/20 00:28:15 jhill * ca server installation * * */ #define CAS_VERSION_GLOBAL #define caServerGlobal #include "server.h" #include "casCtxIL.h" // casCtx in line func static const osiTime CAServerMaxBeaconPeriod (5.0 /* sec */); static const osiTime CAServerMinBeaconPeriod (1.0e-3 /* sec */); // // caServerI::show() // void caServerI::show (unsigned level) const { int bytes_reserved; printf( "Channel Access Server Status V%d.%d\n", CA_PROTOCOL_VERSION, CA_MINOR_VERSION); this->osiMutex::show(level); this->osiLock(); const tsDLIterBD eolSC; tsDLIterBD iterCl(this->clientList.first()); while ( iterCl!=eolSC ) { iterCl->show(level); ++iterCl; } this->dgClient.show(level); const tsDLIterBD eolIOS; tsDLIterBD iterIF(this->intfList.first()); while ( iterIF!=eolIOS ) { iterIF->show(level); ++iterIF; } this->osiUnlock(); bytes_reserved = 0u; #if 0 bytes_reserved += sizeof(casClient) * ellCount(&this->freeClientQ); bytes_reserved += sizeof(casChannel) * ellCount(&this->freeChanQ); bytes_reserved += sizeof(casEventBlock) * ellCount(&this->freeEventQ); bytes_reserved += sizeof(casAsyncIIO) * ellCount(&this->freePendingIO); #endif if (level>=1) { printf( "There are currently %d bytes on the server's free list\n", bytes_reserved); #if 0 printf( "%d client(s), %d channel(s), %d event(s) (monitors), and %d IO blocks\n", ellCount(&this->freeClientQ), ellCount(&this->freeChanQ), ellCount(&this->freeEventQ), ellCount(&this->freePendingIO)); #endif printf( "The server's integer resource id conversion table:\n"); this->osiLock(); this->uintResTable::show(level); this->osiUnlock(); } // @@@@@@ caPrintAddrList(&destAddr); return; } // // caServerI::caServerI() // caServerI::caServerI (caServer &tool, unsigned nPV) : caServerOS(*this), casEventRegistry(* (osiMutex *) this), dgClient(*this), // // Set up periodic beacon interval // (exponential back off to a plateau // from this intial period) // beaconPeriod(CAServerMinBeaconPeriod), adapter(tool), debugLevel(0u), pvCountEstimate(nPV<100u?100u:nPV), haveBeenInitialized(FALSE) { caStatus status; assert(&adapter); //ctx.setServer(this); status = this->init(); if (status) { errMessage(status, "CA server internals init"); } } // // caServerI::init() // caStatus caServerI::init() { int status; int resLibStatus; if (this->osiMutex::init()) { return S_cas_noMemory; } status = casEventRegistry::init(); if (status) { return status; } status = caServerIO::init(*this); if (status) { return status; } if (this->intfList.count()==0u) { return S_cas_noInterface; } status = caServerOS::init(); if (status) { return status; } status = this->dgClient.init(); if (status) { return status; } // // hash table size may need adjustment here? // resLibStatus = this->uintResTable::init(this->pvCountEstimate*2u); if (resLibStatus) { ca_printf("CAS: integer resource id table init failed\n"); return S_cas_noMemory; } this->haveBeenInitialized = TRUE; return S_cas_success; } /* * caServerI::~caServerI() */ caServerI::~caServerI() { this->osiLock(); // // delete all clients // tsDLIterBD iter(this->clientList.first()); tsDLIterBD eol; tsDLIterBD tmp; while ( iter!=eol ) { tmp = iter; ++tmp; // // destructor takes client out of list // casStrmClient *pC = iter; delete pC; iter = tmp; } casIntfOS *pIF; while ( (pIF = this->intfList.get()) ) { delete pIF; } this->osiUnlock(); } // // caServerI::installClient() // void caServerI::installClient(casStrmClient *pClient) { this->osiLock(); this->clientList.add(*pClient); this->osiUnlock(); } // // caServerI::removeClient() // void caServerI::removeClient(casStrmClient *pClient) { this->osiLock(); this->clientList.remove(*pClient); this->osiUnlock(); } // // caServerI::connectCB() // void caServerI::connectCB(casIntfOS &intf) { casStreamOS *pNewClient; caStatus status; pNewClient = intf.newStreamClient(*this); if (!pNewClient) { errMessage(S_cas_noMemory, NULL); return; } status = pNewClient->init(); if (status) { errMessage(status, NULL); delete pNewClient; } } // // caServerI::advanceBeaconPeriod() // // compute delay to the next beacon // void caServerI::advanceBeaconPeriod() { // // return if we are already at the plateau // if (this->beaconPeriod >= CAServerMaxBeaconPeriod) { return; } this->beaconPeriod += this->beaconPeriod; if (this->beaconPeriod >= CAServerMaxBeaconPeriod) { this->beaconPeriod = CAServerMaxBeaconPeriod; } } // // casVerifyFunc() // void casVerifyFunc(const char *pFile, unsigned line, const char *pExp) { fprintf(stderr, "the expression \"%s\" didnt evaluate to boolean true \n", pExp); fprintf(stderr, "and therefore internal problems are suspected at line %u in \"%s\"\n", line, pFile); fprintf(stderr, "Please forward above text to johill@lanl.gov - thanks\n"); } // // serverToolDebugFunc() // void serverToolDebugFunc(const char *pFile, unsigned line, const char *pComment) { fprintf(stderr, "Bad server tool response detected at line %u in \"%s\" because \"%s\"\n", line, pFile, pComment); } // // caServerI::addAddr() // caStatus caServerI::addAddr(const caNetAddr &addr, int autoBeaconAddr, int addConfigBeaconAddr) { caStatus stat; casIntfOS *pIntf; pIntf = new casIntfOS(*this); if (pIntf) { stat = pIntf->init(addr, this->dgClient, autoBeaconAddr, addConfigBeaconAddr); if (stat==S_cas_success) { this->osiLock(); this->intfList.add(*pIntf); this->osiUnlock(); } else { errMessage(stat, NULL); delete pIntf; } } else { stat = S_cas_noMemory; } return stat; } // // caServerI::sendBeacon() // (implemented here because this has knowledge of the protocol) // void caServerI::sendBeacon() { // // send a broadcast beacon over each configured // interface unless EPICS_CA_AUTO_ADDR_LIST specifies // otherwise. Also send a beacon to all configured // addresses. // this->osiLock(); tsDLIterBD iter(this->intfList.first()); while ( iter ) { iter->requestBeacon(); iter++; } this->osiUnlock(); // // double the period between beacons (but dont exceed max) // this->advanceBeaconPeriod(); }