Merged dbServer-api branch

This commit is contained in:
Andrew Johnson
2014-09-26 10:21:40 -05:00
9 changed files with 220 additions and 60 deletions

View File

@@ -15,6 +15,18 @@ EPICS Base 3.15.0.x releases are not intended for use in production systems.</p>
<h2 align="center">Changes between 3.15.0.1 and 3.15.0.2</h2>
<!-- Insert new items immediately below here ... -->
<h3>Added optional dbServer API to database</h3>
<p>A server layer that sits on top of the IOC database may now register itself
as such by calling <tt>dbRegisterServer()</tt> and providing optional routines
that other components can use. The initial purpose of this API allows the Trace
Processing implementation in <tt>dbProcess()</tt> to identify a client that
causes a record to process when TPRO is set.</p>
<p>To support the client idenfication, the server provides a routine that
returns that identity string when called by one of its own processing
threads.</p>
<h3>Concatenated database definition files</h3>
<p>A series of database definition (dbd) files can now be concatenated during

View File

@@ -26,6 +26,7 @@ INC += dbLink.h
INC += dbLock.h
INC += dbNotify.h
INC += dbScan.h
INC += dbServer.h
INC += dbTest.h
INC += dbCaTest.h
INC += db_test.h
@@ -88,3 +89,5 @@ dbCore_SRCS += dbIocRegister.c
dbCore_SRCS += chfPlugin.c
dbCore_SRCS += dbState.c
dbCore_SRCS += dbUnitTest.c
dbCore_SRCS += dbServer.c

View File

@@ -59,6 +59,7 @@
#include "dbNotify.h"
#include "dbAccessDefs.h"
#include "recGbl.h"
#include "dbServer.h"
epicsShareDef struct dbBase *pdbbase = 0;
epicsShareDef volatile int interruptAccept=FALSE;
@@ -454,6 +455,7 @@ long dbProcess(dbCommon *precord)
struct rset *prset = precord->rset;
dbRecordType *pdbRecordType = precord->rdes;
unsigned char tpro = precord->tpro;
char context[40] = "";
long status = 0;
int *ptrace;
int set_trace = FALSE;
@@ -484,23 +486,33 @@ long dbProcess(dbCommon *precord)
/* check for trace processing*/
if (tpro) {
if(*ptrace==0) {
if (!*ptrace) {
*ptrace = 1;
set_trace = TRUE;
}
}
if (*ptrace) {
/* Identify this thread's client from server layer */
if (dbServerClient(context, sizeof(context))) {
/* No client, use thread name */
strncpy(context, epicsThreadGetNameSelf(), sizeof(context));
context[sizeof(context) - 1] = 0;
}
}
/* If already active dont process */
if (precord->pact) {
unsigned short monitor_mask;
unsigned short monitor_mask;
if (*ptrace)
printf("%s: Active %s\n",
epicsThreadGetNameSelf(), precord->name);
printf("%s: Active %s\n", context, precord->name);
/* raise scan alarm after MAX_LOCK times */
if (precord->stat==SCAN_ALARM) goto all_done;
if (precord->lcnt++ !=MAX_LOCK) goto all_done;
if (precord->sevr>=INVALID_ALARM) goto all_done;
if ((precord->stat == SCAN_ALARM) ||
(precord->lcnt++ < MAX_LOCK) ||
(precord->sevr >= INVALID_ALARM)) goto all_done;
recGblSetSevr(precord, SCAN_ALARM, INVALID_ALARM);
monitor_mask = recGblResetAlarms(precord);
monitor_mask |= DBE_VALUE|DBE_LOG;
@@ -510,7 +522,8 @@ long dbProcess(dbCommon *precord)
monitor_mask);
goto all_done;
}
else precord->lcnt = 0;
else
precord->lcnt = 0;
/*
* Check the record disable link. A record will not be
@@ -521,9 +534,8 @@ long dbProcess(dbCommon *precord)
/* if disabled check disable alarm severity and return success */
if (precord->disa == precord->disv) {
if(*ptrace)
printf("%s: Disabled %s\n",
epicsThreadGetNameSelf(), precord->name);
if (*ptrace)
printf("%s: Disabled %s\n", context, precord->name);
/*take care of caching and notifyCompletion*/
precord->rpro = FALSE;
@@ -531,7 +543,9 @@ long dbProcess(dbCommon *precord)
callNotifyCompletion = TRUE;
/* raise disable alarm */
if (precord->stat==DISABLE_ALARM) goto all_done;
if (precord->stat == DISABLE_ALARM)
goto all_done;
precord->sevr = precord->diss;
precord->stat = DISABLE_ALARM;
precord->nsev = 0;
@@ -547,29 +561,34 @@ long dbProcess(dbCommon *precord)
/* locate record processing routine */
/* FIXME: put this in iocInit() !!! */
if (!(prset=precord->rset) || !(prset->process)) {
if (!prset || !prset->process) {
callNotifyCompletion = TRUE;
precord->pact=1;/*set pact TRUE so error is issued only once*/
precord->pact = 1;/*set pact so error is issued only once*/
recGblRecordError(S_db_noRSET, (void *)precord, "dbProcess");
status = S_db_noRSET;
if (*ptrace)
printf("%s: No RSET for %s\n",
epicsThreadGetNameSelf(), precord->name);
printf("%s: No RSET for %s\n", context, precord->name);
goto all_done;
}
if(*ptrace)
printf("%s: Process %s\n",
epicsThreadGetNameSelf(), precord->name);
if (*ptrace)
printf("%s: Process %s\n", context, precord->name);
/* process record */
status = (*prset->process)(precord);
status = prset->process(precord);
/* Print record's fields if PRINT_MASK set in breakpoint field */
if (lset_stack_count != 0) {
dbPrint(precord);
}
all_done:
if (set_trace) *ptrace = 0;
if(callNotifyCompletion && precord->ppn) dbNotifyCompletion(precord);
return(status);
if (set_trace)
*ptrace = 0;
if (callNotifyCompletion && precord->ppn)
dbNotifyCompletion(precord);
return status;
}
/*

View File

@@ -18,6 +18,7 @@
#include "db_test.h"
#include "dbLock.h"
#include "dbScan.h"
#include "dbServer.h"
#include "dbNotify.h"
#include "callback.h"
#include "dbIocRegister.h"
@@ -90,6 +91,12 @@ static const iocshArg * const dbapArgs[1] = {&dbapArg0};
static const iocshFuncDef dbapFuncDef = {"dbap",1,dbapArgs};
static void dbapCallFunc(const iocshArgBuf *args) { dbap(args[0].sval);}
/* dbsr */
static const iocshArg dbsrArg0 = { "interest level",iocshArgInt};
static const iocshArg * const dbsrArgs[1] = {&dbsrArg0};
static const iocshFuncDef dbsrFuncDef = {"dbsr",1,dbsrArgs};
static void dbsrCallFunc(const iocshArgBuf *args) { dbsr(args[0].ival);}
/* dbcar */
static const iocshArg dbcarArg0 = { "record name",iocshArgString};
static const iocshArg dbcarArg1 = { "level",iocshArgInt};
@@ -360,6 +367,7 @@ void dbIocRegister(void)
iocshRegister(&dbpFuncDef,dbpCallFunc);
iocshRegister(&dbapFuncDef,dbapCallFunc);
iocshRegister(&dbsrFuncDef,dbsrCallFunc);
iocshRegister(&dbcarFuncDef,dbcarCallFunc);
iocshRegister(&dbelFuncDef,dbelCallFunc);

58
src/ioc/db/dbServer.c Normal file
View File

@@ -0,0 +1,58 @@
/*************************************************************************\
* Copyright (c) 2014 UChicago Argonne LLC, as Operator of Argonne
* National Laboratory.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
* Author: Andrew Johnson <anj@aps.anl.gov>
*/
#include <stddef.h>
#include "ellLib.h"
#include "epicsStdio.h"
#define epicsExportSharedSymbols
#include "dbServer.h"
static ELLLIST serverList = ELLLIST_INIT;
void dbRegisterServer(dbServer *psrv)
{
if (ellNext(&psrv->node)) {
fprintf(stderr, "dbRegisterServer: '%s' registered twice?\n",
psrv->name);
return;
}
ellAdd(&serverList, &psrv->node);
}
void dbsr(unsigned level)
{
dbServer *psrv = (dbServer *)ellFirst(&serverList);
while (psrv) {
printf("Server '%s':\n", psrv->name);
if (psrv->report)
psrv->report(level);
psrv = (dbServer *)ellNext(&psrv->node);
}
}
int dbServerClient(char *pBuf, size_t bufSize)
{
dbServer *psrv = (dbServer *)ellFirst(&serverList);
while (psrv) {
if (psrv->client &&
psrv->client(pBuf, bufSize) == 0)
return 0;
psrv = (dbServer *)ellNext(&psrv->node);
}
return -1;
}

58
src/ioc/db/dbServer.h Normal file
View File

@@ -0,0 +1,58 @@
/*************************************************************************\
* Copyright (c) 2014 UChicago Argonne LLC, as Operator of Argonne
* National Laboratory.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
* Author: Andrew Johnson <anj@aps.anl.gov>
*/
#ifndef INC_dbServer_H
#define INC_dbServer_H
#include <stddef.h>
#include "ellLib.h"
#include "shareLib.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Server information structure */
typedef struct dbServer {
ELLNODE node;
const char *name;
/* Print level-dependent status report to stdout */
void (* report) (unsigned level);
/* Get number of channels and clients connected */
void (* stats) (unsigned *channels, unsigned *clients);
/* Get identity of client initiating the calling thread */
/* Must return 0 (OK), or -1 (ERROR) from unknown threads */
int (* client) (char *pBuf, size_t bufSize);
} dbServer;
epicsShareFunc void dbRegisterServer(dbServer *psrv);
/* Extra routines could be added if/when needed:
*
* epicsShareFunc const dbServer* dbFindServer(const char *name);
* epicsShareFunc void dbIterateServers(srvIterFunc func, void *user);
*/
epicsShareFunc void dbsr(unsigned level);
epicsShareFunc int dbServerClient(char *pBuf, size_t bufSize);
#ifdef __cplusplus
}
#endif
#endif /* INC_dbServer_H */

View File

@@ -17,13 +17,13 @@
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include "dbDefs.h"
#include "osiSock.h"
#include "epicsTime.h"
#include "epicsStdio.h"
#include "errlog.h"
#include "taskwd.h"
#include "db_access.h"
@@ -165,35 +165,18 @@ void camsgtask ( void *pParm )
}
void casHostNameInitiatingCurrentThread ( char * pBuf, unsigned bufSize )
int casClientInitiatingCurrentThread ( char * pBuf, size_t bufSize )
{
if ( bufSize ) {
const char * pHostName = "";
{
struct client * pClient = ( struct client * )
epicsThreadPrivateGet ( rsrvCurrentClient );
if ( pClient ) {
pHostName = pClient->pHostName;
}
}
strncpy ( pBuf, pHostName, bufSize );
pBuf [ bufSize - 1u ] = '\0';
}
}
void casUserNameInitiatingCurrentThread ( char * pBuf, unsigned bufSize )
{
if ( bufSize ) {
const char * pUserName = "";
{
struct client * pClient = ( struct client * )
epicsThreadPrivateGet ( rsrvCurrentClient );
if ( pClient ) {
pUserName = pClient->pUserName;
}
}
strncpy ( pBuf, pUserName, bufSize );
pBuf [ bufSize - 1u ] = '\0';
struct client * pClient = ( struct client * )
epicsThreadPrivateGet ( rsrvCurrentClient );
if ( ! pClient )
return RSRV_ERROR;
if ( pBuf && bufSize ) {
epicsSnprintf(pBuf, bufSize, "ca:%s@%s",
pClient->pUserName, pClient->pHostName);
}
return RSRV_OK;
}

View File

@@ -39,12 +39,14 @@
#include "dbEvent.h"
#include "dbChannel.h"
#include "dbCommon.h"
#include "dbServer.h"
#include "rsrv.h"
#define GLBLSOURCE
#include "server.h"
#define DELETE_TASK(NAME)\
if(threadNameToId(NAME)!=0)threadDestroy(threadNameToId(NAME));
#define DELETE_TASK(NAME) \
if (threadNameToId(NAME)!=0) \
threadDestroy(threadNameToId(NAME));
epicsThreadPrivateId rsrvCurrentClient;
@@ -246,6 +248,14 @@ static void req_server (void *pParm)
}
}
static dbServer rsrv_server = {
ELLNODE_INIT,
"rsrv",
casr,
casStatsFetch,
casClientInitiatingCurrentThread
};
/*
* rsrv_init ()
*/
@@ -266,6 +276,8 @@ int rsrv_init (void)
freeListInitPvt ( &rsrvSmallBufFreeListTCP, MAX_TCP, 16 );
initializePutNotifyFreeList ();
dbRegisterServer(&rsrv_server);
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" );

View File

@@ -19,21 +19,28 @@
#ifndef rsrvh
#define rsrvh
#include <stddef.h>
#include "shareLib.h"
#define RSRV_OK 0
#define RSRV_ERROR (-1)
#ifdef __cplusplus
extern "C" {
#endif
epicsShareFunc int rsrv_init(void);
epicsShareFunc int rsrv_run(void);
epicsShareFunc int rsrv_pause(void);
epicsShareFunc void casr (unsigned level);
epicsShareFunc void casHostNameInitiatingCurrentThread (
char * pBuf, unsigned bufSize );
epicsShareFunc void casUserNameInitiatingCurrentThread (
char * pBuf, unsigned bufSize );
epicsShareFunc int casClientInitiatingCurrentThread (
char * pBuf, size_t bufSize );
epicsShareFunc void casStatsFetch (
unsigned *pChanCount, unsigned *pConnCount );
#define RSRV_OK 0
#define RSRV_ERROR (-1)
#ifdef __cplusplus
}
#endif
#endif /*rsrvh */