installed

This commit is contained in:
Jeff Hill
2000-04-28 00:54:26 +00:00
parent a18943ad9f
commit 52467d71dd
5 changed files with 640 additions and 0 deletions

112
src/db/dbCAC.h Normal file
View File

@@ -0,0 +1,112 @@
/*
* $Id$
*
*
* L O S A L A M O S
* Los Alamos National Laboratory
* Los Alamos, New Mexico 87545
*
* Copyright, 1986, The Regents of the University of California.
*
*
* Author Jeffrey O. Hill
* johill@lanl.gov
* 505 665 1831
*
* NOTES:
* 1) This interface is preliminary and will change in the future
*/
#include "dbNotify.h"
#include "dbEvent.h"
#include "dbAddr.h"
extern "C" void putNotifyCompletion ( putNotify *ppn );
class dbPutNotifyIO : public cacNotifyIO {
public:
dbPutNotifyIO ( cacNotify &notify );
int initiate ( struct dbAddr &addr, unsigned type,
unsigned long count, const void *pValue);
void destroy ();
static void * operator new ( size_t size );
static void operator delete ( void *pCadaver, size_t size );
private:
putNotify pn;
bool ioComplete;
static tsFreeList < dbPutNotifyIO > freeList;
~dbPutNotifyIO (); // must allocate out of pool
friend void putNotifyCompletion ( putNotify *ppn );
};
class dbChannelIO;
extern "C" void dbSubscriptionEventCallback ( void *pPrivate, struct dbAddr *paddr,
int eventsRemaining, struct db_field_log *pfl );
class dbSubscriptionIO : public cacNotifyIO {
public:
dbSubscriptionIO ( dbChannelIO &chanIO, cacNotify &, unsigned type, unsigned long count );
int dbSubscriptionIO::begin ( struct dbAddr &addr, unsigned mask );
void destroy ();
static void * operator new ( size_t size );
static void operator delete ( void *pCadaver, size_t size );
private:
dbChannelIO &chan;
dbEventSubscription es;
unsigned type;
unsigned long count;
static tsFreeList < dbSubscriptionIO > freeList;
~dbSubscriptionIO (); // must be allocated from pool
friend void dbSubscriptionEventCallback ( void *user_arg, struct dbAddr *paddr,
int eventsRemaining, struct db_field_log *pfl );
};
class dbServiceIO;
class dbChannelIO : public cacChannelIO {
public:
dbChannelIO ( cacChannel &chan, const dbAddr &addr, dbServiceIO &serviceIO );
void destroy ();
void subscriptionUpdate ( unsigned type, unsigned long count,
const struct db_field_log *pfl, cacNotifyIO &notify);
dbEventSubscription subscribe ( dbSubscriptionIO &subscr, unsigned mask );
static void * operator new ( size_t size);
static void operator delete ( void *pCadaver, size_t size );
private:
dbServiceIO &serviceIO;
char *pGetCallbackCache;
unsigned long getCallbackCacheSize;
dbAddr addr;
static tsFreeList < dbChannelIO > freeList;
~dbChannelIO (); // allocate only from pool
const char *pName () const;
int read ( unsigned type, unsigned long count, void *pValue );
int read ( unsigned type, unsigned long count, cacNotify & );
int write ( unsigned type, unsigned long count, const void *pvalue );
int write ( unsigned type, unsigned long count, const void *pvalue, cacNotify & );
int subscribe ( unsigned type, unsigned long count, unsigned mask, cacNotify &notify );
short nativeType () const;
unsigned long nativeElementCount () const;
};
class dbServiceIO : public cacServiceIO {
public:
dbServiceIO ();
~dbServiceIO ();
cacChannelIO *createChannelIO ( cacChannel &chan, const char *pName );
void subscriptionUpdate ( struct dbAddr &addr, unsigned type, unsigned long count,
const struct db_field_log *pfl, cacNotifyIO &notify );
dbEventSubscription subscribe ( struct dbAddr &addr, dbSubscriptionIO &subscr, unsigned mask );
private:
dbEventCtx ctx;
char *pEventCallbackCache;
unsigned long eventCallbackCacheSize;
osiMutex mutex;
};

194
src/db/dbChannelIO.cpp Normal file
View File

@@ -0,0 +1,194 @@
/*
* $Id$
*
*
* L O S A L A M O S
* Los Alamos National Laboratory
* Los Alamos, New Mexico 87545
*
* Copyright, 1986, The Regents of the University of California.
*
*
* Author Jeffrey O. Hill
* johill@lanl.gov
* 505 665 1831
*/
#include "limits.h"
#include "tsFreeList.h"
#include "osiMutex.h"
#include "cadef.h"
#include "cacIO.h"
#define epicsExportSharedSymbols
#include "db_access_routines.h"
#include "dbCAC.h"
#include "dbLock.h"
#include "dbCommon.h"
extern "C" unsigned short dbDBRnewToDBRold[DBR_ENUM+1];
tsFreeList < dbChannelIO > dbChannelIO::freeList;
dbChannelIO::dbChannelIO ( cacChannel &chan, const dbAddr &addrIn, dbServiceIO &serviceIO ) :
cacChannelIO ( chan ), serviceIO ( serviceIO ), addr ( addrIn ),
pGetCallbackCache ( 0 ), getCallbackCacheSize ( 0ul )
{
this->connectNotify ();
}
dbChannelIO::~dbChannelIO ()
{
if ( this->pGetCallbackCache ) {
delete [] this->pGetCallbackCache;
}
}
void dbChannelIO::destroy ()
{
delete this;
}
void * dbChannelIO::operator new ( size_t size )
{
return dbChannelIO::freeList.allocate ( size );
}
void dbChannelIO::operator delete ( void *pCadaver, size_t size )
{
dbChannelIO::freeList.release ( pCadaver, size );
}
const char *dbChannelIO::pName () const
{
return addr.precord->name;
}
int dbChannelIO::read ( unsigned type, unsigned long count, void *pValue )
{
if ( type > INT_MAX ) {
return ECA_BADCOUNT;
}
if ( count > INT_MAX ) {
return ECA_BADCOUNT;
}
int status = db_get_field ( &this->addr, static_cast <int> ( type ),
pValue, static_cast <int> ( count ), 0);
if ( status ) {
return ECA_GETFAIL;
}
else {
return ECA_NORMAL;
}
}
int dbChannelIO::read ( unsigned type, unsigned long count, cacNotify &notify )
{
unsigned long size = dbr_size_n ( type, count );
if ( type > INT_MAX ) {
return ECA_BADCOUNT;
}
if ( count > INT_MAX ) {
return ECA_BADCOUNT;
}
dbScanLock ( this->addr.precord );
if ( this->getCallbackCacheSize < size) {
if ( this->pGetCallbackCache ) {
delete [] this->pGetCallbackCache;
}
this->pGetCallbackCache = new char [size];
if ( ! this->pGetCallbackCache ) {
this->getCallbackCacheSize = 0ul;
dbScanUnlock ( this->addr.precord );
return ECA_ALLOCMEM;
}
this->getCallbackCacheSize = size;
}
int status = db_get_field ( &this->addr, static_cast <int> ( type ),
this->pGetCallbackCache, static_cast <int> ( count ), 0);
if ( status ) {
notify.exceptionNotify ( ECA_GETFAIL, "db_get_field () completed unsuccessfuly" );
}
else {
notify.completionNotify ( type, count, this->pGetCallbackCache );
}
notify.destroy ();
dbScanUnlock ( this->addr.precord );
return ECA_NORMAL;
}
int dbChannelIO::write ( unsigned type, unsigned long count, const void *pValue )
{
int status;
if ( count > LONG_MAX ) {
return ECA_BADCOUNT;
}
status = db_put_field ( &this->addr, type, pValue, static_cast <long> (count) );
if (status) {
return ECA_PUTFAIL;
}
else {
return ECA_NORMAL;
}
}
int dbChannelIO::write ( unsigned type, unsigned long count,
const void *pValue, cacNotify &notify )
{
dbPutNotifyIO *pIO;
if ( count > LONG_MAX ) {
return ECA_BADCOUNT;
}
pIO = new dbPutNotifyIO ( notify );
if ( ! pIO ) {
return ECA_ALLOCMEM;
}
int status = pIO->initiate ( this->addr, type, count, pValue );
if ( status != ECA_NORMAL ) {
pIO->destroy ();
}
return status;
}
int dbChannelIO::subscribe ( unsigned type, unsigned long count,
unsigned mask, cacNotify &notify )
{
dbSubscriptionIO *pIO = new dbSubscriptionIO ( *this, notify, type, count );
if ( ! pIO ) {
return ECA_ALLOCMEM;
}
int status = pIO->begin ( this->addr, mask );
if ( status != ECA_NORMAL ) {
pIO->destroy ();
}
return status;
}
short dbChannelIO::nativeType () const
{
return dbDBRnewToDBRold[this->addr.field_type];
}
unsigned long dbChannelIO::nativeElementCount () const
{
if ( this->addr.no_elements >= 0u ) {
return static_cast < unsigned long > ( this->addr.no_elements );
}
else {
return 0u;
}
}
void dbChannelIO::subscriptionUpdate ( unsigned type, unsigned long count,
const struct db_field_log *pfl, cacNotifyIO &notify )
{
this->serviceIO.subscriptionUpdate ( this->addr, type, count, pfl, notify );
}
dbEventSubscription dbChannelIO::subscribe ( dbSubscriptionIO &subscr, unsigned mask )
{
return this->serviceIO.subscribe ( this->addr, subscr, mask );
}

109
src/db/dbPutNotifyIO.cpp Normal file
View File

@@ -0,0 +1,109 @@
/*
* $Id$
*
*
* L O S A L A M O S
* Los Alamos National Laboratory
* Los Alamos, New Mexico 87545
*
* Copyright, 1986, The Regents of the University of California.
*
*
* Author Jeffrey O. Hill
* johill@lanl.gov
* 505 665 1831
*/
#include "limits.h"
#include "string.h"
#include "osiMutex.h"
#include "tsFreeList.h"
#include "errMdef.h"
#include "cadef.h"
#include "cacIO.h"
#define epicsExportSharedSymbols
#include "dbCAC.h"
#define S_db_Blocked (M_dbAccess|39)
#define S_db_Pending (M_dbAccess|37)
tsFreeList <dbPutNotifyIO> dbPutNotifyIO::freeList;
extern "C" void putNotifyCompletion ( putNotify *ppn )
{
dbPutNotifyIO *pNotify = static_cast < dbPutNotifyIO * > ( ppn->usrPvt );
if ( pNotify->pn.status ) {
if (pNotify->pn.status == S_db_Blocked) {
pNotify->cacNotifyIO::exceptionNotify ( ECA_PUTCBINPROG, "put notify blocked" );
}
else {
pNotify->cacNotifyIO::exceptionNotify ( ECA_PUTFAIL, "put notify unsuccessful");
}
}
else {
pNotify->cacNotifyIO::completionNotify ();
}
pNotify->ioComplete = true;
pNotify->destroy ();
}
dbPutNotifyIO::dbPutNotifyIO ( cacNotify &notifyIn ) :
cacNotifyIO (notifyIn), ioComplete (false)
{
memset (&this->pn, '\0', sizeof (this->pn));
this->pn.userCallback = putNotifyCompletion;
this->pn.usrPvt = this;
}
dbPutNotifyIO::~dbPutNotifyIO ()
{
if ( ! this->ioComplete ) {
dbNotifyCancel ( &this->pn );
}
}
int dbPutNotifyIO::initiate ( struct dbAddr &addr, unsigned type,
unsigned long count, const void *pValue)
{
int status;
if ( count > LONG_MAX ) {
return ECA_BADCOUNT;
}
if ( type > SHRT_MAX ) {
return ECA_BADTYPE;
}
this->pn.pbuffer = const_cast <void *> ( pValue );
this->pn.nRequest = static_cast <unsigned> ( count );
this->pn.paddr = &addr;
status = this->pn.dbrType = dbPutNotifyMapType ( &this->pn, static_cast <short> ( type ) );
if (status) {
return ECA_BADTYPE;
}
status = ::dbPutNotify ( &this->pn );
if ( status && status != S_db_Pending ) {
this->pn.status = status;
putNotifyCallback ();
}
return ECA_NORMAL;
}
void dbPutNotifyIO::destroy ()
{
delete this;
}
void * dbPutNotifyIO::operator new ( size_t size )
{
return dbPutNotifyIO::freeList.allocate ( size );
}
void dbPutNotifyIO::operator delete ( void *pCadaver, size_t size )
{
dbPutNotifyIO::freeList.release ( pCadaver, size );
}

141
src/db/dbServiceIO.cpp Normal file
View File

@@ -0,0 +1,141 @@
/*
* $Id$
*
*
* L O S A L A M O S
* Los Alamos National Laboratory
* Los Alamos, New Mexico 87545
*
* Copyright, 1986, The Regents of the University of California.
*
*
* Author Jeffrey O. Hill
* johill@lanl.gov
* 505 665 1831
*/
#include "limits.h"
#include "osiMutex.h"
#include "tsFreeList.h"
#include "cadef.h"
#include "cacIO.h"
#define epicsExportSharedSymbols
#include "db_access_routines.h"
#include "dbCAC.h"
class loadTimeInit {
public:
loadTimeInit ();
private:
dbServiceIO dbio;
};
static loadTimeInit lti;
loadTimeInit::loadTimeInit ()
{
cacGlobalServiceList.registerService ( this->dbio );
}
dbServiceIO::dbServiceIO () :
ctx (0), pEventCallbackCache (0), eventCallbackCacheSize (0ul)
{
}
dbServiceIO::~dbServiceIO ()
{
if ( this->pEventCallbackCache ) {
delete [] this->pEventCallbackCache;
}
if (this->ctx) {
db_close_events (this->ctx);
}
}
cacChannelIO *dbServiceIO::createChannelIO ( cacChannel &chan, const char *pName )
{
struct dbAddr addr;
int status = db_name_to_addr ( pName, &addr );
if (status) {
return 0;
}
else {
return new dbChannelIO ( chan, addr, *this );
}
}
void dbServiceIO::subscriptionUpdate ( struct dbAddr &addr, unsigned type, unsigned long count,
const struct db_field_log *pfl, cacNotifyIO &notify )
{
unsigned long size = dbr_size_n ( type, count );
this->mutex.lock ();
if ( this->eventCallbackCacheSize < size) {
if ( this->pEventCallbackCache ) {
delete [] this->pEventCallbackCache;
}
this->pEventCallbackCache = new char [size];
if ( ! this->pEventCallbackCache ) {
this->eventCallbackCacheSize = 0ul;
this->mutex.unlock ();
notify.exceptionNotify ( ECA_ALLOCMEM, "unable to allocate callback cache" );
return;
}
this->eventCallbackCacheSize = size;
}
void *pvfl = (void *) pfl;
int status = db_get_field ( &addr, static_cast <int> ( type ),
this->pEventCallbackCache, static_cast <int> ( count ), pvfl );
if ( status ) {
notify.exceptionNotify ( ECA_GETFAIL, "subscription update db_get_field () completed unsuccessfuly" );
}
else {
notify.completionNotify ( type, count, this->pEventCallbackCache );
}
this->mutex.unlock ();
}
extern "C" void cacAttachClientCtx ( void * pPrivate )
{
int status;
caClientCtx clientCtx = pPrivate;
status = ca_attach_context ( clientCtx );
assert ( status == ECA_NORMAL );
}
dbEventSubscription dbServiceIO::subscribe ( struct dbAddr &addr, dbSubscriptionIO &subscr, unsigned mask )
{
static const int slightlyHigherPriority = -1;
int status;
caClientCtx clientCtx;
status = ca_current_context ( &clientCtx );
if ( status != ECA_NORMAL ) {
return 0;
}
this->mutex.lock ();
if ( ! this->ctx ) {
this->ctx = db_init_events ();
if ( ! this->ctx ) {
this->mutex.unlock ();
return 0;
}
status = db_start_events ( this->ctx, "CAC event",
cacAttachClientCtx, clientCtx, slightlyHigherPriority );
if ( status ) {
db_close_events (this->ctx);
this->ctx = 0;
return 0;
}
}
this->mutex.unlock ();
return db_add_event ( this->ctx, &addr,
dbSubscriptionEventCallback, (void *) &subscr, mask );
}

View File

@@ -0,0 +1,84 @@
/*
* $Id$
*
*
* L O S A L A M O S
* Los Alamos National Laboratory
* Los Alamos, New Mexico 87545
*
* Copyright, 1986, The Regents of the University of California.
*
*
* Author Jeffrey O. Hill
* johill@lanl.gov
* 505 665 1831
*/
#include "limits.h"
#include "osiMutex.h"
#include "tsFreeList.h"
#include "cadef.h"
#include "cacIO.h"
#define epicsExportSharedSymbols
#include "dbCAC.h"
#include "db_access_routines.h"
tsFreeList < dbSubscriptionIO > dbSubscriptionIO::freeList;
dbSubscriptionIO::dbSubscriptionIO ( dbChannelIO &chanIO,
cacNotify &notifyIn, unsigned typeIn, unsigned long countIn ) :
cacNotifyIO ( notifyIn ), chan ( chanIO ), es ( 0 ),
type ( typeIn ), count ( countIn )
{
}
dbSubscriptionIO::~dbSubscriptionIO ()
{
if ( this->es ) {
db_cancel_event ( this->es );
}
}
void dbSubscriptionIO::destroy ()
{
delete this;
}
void * dbSubscriptionIO::operator new ( size_t size )
{
return dbSubscriptionIO::freeList.allocate ( size );
}
void dbSubscriptionIO::operator delete ( void *pCadaver, size_t size )
{
dbSubscriptionIO::freeList.release ( pCadaver, size );
}
extern "C" void dbSubscriptionEventCallback ( void *pPrivate, struct dbAddr *paddr,
int eventsRemaining, struct db_field_log *pfl )
{
dbSubscriptionIO *pIO = static_cast <dbSubscriptionIO *> ( pPrivate );
pIO->chan.subscriptionUpdate ( pIO->type, pIO->count, pfl, *pIO);
}
int dbSubscriptionIO::begin ( struct dbAddr &addr, unsigned mask )
{
if ( this->type > INT_MAX ) {
return ECA_BADCOUNT;
}
if ( this->count > INT_MAX ) {
return ECA_BADCOUNT;
}
this->es = this->chan.subscribe ( *this, mask );
if ( this->es ) {
return ECA_NORMAL;
}
else {
return ECA_ALLOCMEM;
}
}