From 8857d0bb4e467cb6ef34cd6cfc12eb5fec2f02f0 Mon Sep 17 00:00:00 2001
From: Andrew Johnson
Date: Thu, 29 May 2014 17:09:08 -0500
Subject: [PATCH 1/6] Add dbServer files.
---
src/ioc/db/Makefile | 2 ++
src/ioc/db/dbServer.c | 58 +++++++++++++++++++++++++++++++++++++++++++
src/ioc/db/dbServer.h | 58 +++++++++++++++++++++++++++++++++++++++++++
3 files changed, 118 insertions(+)
create mode 100644 src/ioc/db/dbServer.c
create mode 100644 src/ioc/db/dbServer.h
diff --git a/src/ioc/db/Makefile b/src/ioc/db/Makefile
index c957842cb..5d58542fe 100644
--- a/src/ioc/db/Makefile
+++ b/src/ioc/db/Makefile
@@ -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
@@ -86,4 +87,5 @@ dbCore_SRCS += templateInstances.cpp
dbCore_SRCS += dbIocRegister.c
dbCore_SRCS += chfPlugin.c
dbCore_SRCS += dbState.c
+dbCore_SRCS += dbServer.c
diff --git a/src/ioc/db/dbServer.c b/src/ioc/db/dbServer.c
new file mode 100644
index 000000000..bc1094ce7
--- /dev/null
+++ b/src/ioc/db/dbServer.c
@@ -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
+ */
+
+#include
+
+#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;
+}
+
diff --git a/src/ioc/db/dbServer.h b/src/ioc/db/dbServer.h
new file mode 100644
index 000000000..345468676
--- /dev/null
+++ b/src/ioc/db/dbServer.h
@@ -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
+ */
+
+#ifndef INC_dbServer_H
+#define INC_dbServer_H
+
+#include
+
+#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 */
From fc8ad6b9eccc03416bfcbb9f5122be507ac5ea84 Mon Sep 17 00:00:00 2001
From: Andrew Johnson
Date: Thu, 29 May 2014 17:10:26 -0500
Subject: [PATCH 2/6] rsrv: Register with dbServer API.
---
src/ioc/rsrv/camsgtask.c | 41 +++++++++++--------------------------
src/ioc/rsrv/caservertask.c | 24 ++++++++++++++++------
src/ioc/rsrv/rsrv.h | 19 +++++++++++------
3 files changed, 43 insertions(+), 41 deletions(-)
diff --git a/src/ioc/rsrv/camsgtask.c b/src/ioc/rsrv/camsgtask.c
index 8317b60f4..16af5bb0d 100644
--- a/src/ioc/rsrv/camsgtask.c
+++ b/src/ioc/rsrv/camsgtask.c
@@ -17,13 +17,13 @@
#include
#include
-#include
#include
#include
#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, "%s@%s",
+ pClient->pUserName, pClient->pHostName);
}
+ return RSRV_OK;
}
diff --git a/src/ioc/rsrv/caservertask.c b/src/ioc/rsrv/caservertask.c
index e3ab087f1..34226b72f 100644
--- a/src/ioc/rsrv/caservertask.c
+++ b/src/ioc/rsrv/caservertask.c
@@ -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;
@@ -230,6 +232,14 @@ static void req_server (void *pParm)
}
}
+static dbServer rsrv_server = {
+ ELLNODE_INIT,
+ "rsrv",
+ casr,
+ casStatsFetch,
+ casClientInitiatingCurrentThread
+};
+
/*
* rsrv_init ()
*/
@@ -250,6 +260,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" );
@@ -948,16 +960,16 @@ struct client *create_tcp_client ( SOCKET sock )
void casStatsFetch ( unsigned *pChanCount, unsigned *pCircuitCount )
{
- LOCK_CLIENTQ;
+ LOCK_CLIENTQ;
{
int circuitCount = ellCount ( &clientQ );
if ( circuitCount < 0 ) {
- *pCircuitCount = 0;
+ *pCircuitCount = 0;
}
else {
- *pCircuitCount = (unsigned) circuitCount;
+ *pCircuitCount = (unsigned) circuitCount;
}
*pChanCount = rsrvChannelCount;
}
- UNLOCK_CLIENTQ;
+ UNLOCK_CLIENTQ;
}
diff --git a/src/ioc/rsrv/rsrv.h b/src/ioc/rsrv/rsrv.h
index 4eae9bf5a..84414fc8d 100644
--- a/src/ioc/rsrv/rsrv.h
+++ b/src/ioc/rsrv/rsrv.h
@@ -19,21 +19,28 @@
#ifndef rsrvh
#define rsrvh
+#include
#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 */
From dbe2a890ecc092c8d18bf3959957d62717be4516 Mon Sep 17 00:00:00 2001
From: Andrew Johnson
Date: Thu, 29 May 2014 17:11:31 -0500
Subject: [PATCH 3/6] db: Use dbServer API
Setting TPRO now prints user@hostname instead of the thread
name when a record is processed as a result of a caput.
Also added the dbsr command, which currently just calls casr but
will call all registered server report routines (e.g. pvaSrv).
---
src/ioc/db/dbAccess.c | 65 ++++++++++++++++++++++++--------------
src/ioc/db/dbIocRegister.c | 8 +++++
2 files changed, 50 insertions(+), 23 deletions(-)
diff --git a/src/ioc/db/dbAccess.c b/src/ioc/db/dbAccess.c
index 904423a71..3856d0edc 100644
--- a/src/ioc/db/dbAccess.c
+++ b/src/ioc/db/dbAccess.c
@@ -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[20] = "";
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;
}
/*
diff --git a/src/ioc/db/dbIocRegister.c b/src/ioc/db/dbIocRegister.c
index 0de2d7172..c07dcc730 100644
--- a/src/ioc/db/dbIocRegister.c
+++ b/src/ioc/db/dbIocRegister.c
@@ -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);
From 511b2e4f5c936a962955bac81635857650865244 Mon Sep 17 00:00:00 2001
From: Andrew Johnson
Date: Thu, 29 May 2014 17:34:23 -0500
Subject: [PATCH 4/6] Document briefly.
---
documentation/RELEASE_NOTES.html | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/documentation/RELEASE_NOTES.html b/documentation/RELEASE_NOTES.html
index d20d9bc65..25590d490 100644
--- a/documentation/RELEASE_NOTES.html
+++ b/documentation/RELEASE_NOTES.html
@@ -15,6 +15,18 @@ EPICS Base 3.15.0.x releases are not intended for use in production systems.
Changes between 3.15.0.1 and 3.15.0.2
+Added optional dbServer API to database
+
+A server layer that sits on top of the IOC database may now register itself
+as such by calling dbRegisterServer() and providing optional routines
+that other components can use. The initial purpose of this API allows the Trace
+Processing implementation in dbProcess() to identify a client that
+causes a record to process when TPRO is set.
+
+To support the client idenfication, the server provides a routine that
+returns that identity string when called by one of its own processing
+threads.
+
Added echo command to iocsh
The single argument string may contain escaped characters, which will be
From 42a3b4fbfd1a7c8b0359da6ce56bceba3849c58e Mon Sep 17 00:00:00 2001
From: Andrew Johnson
Date: Thu, 29 May 2014 17:36:04 -0500
Subject: [PATCH 5/6] Add a ca: prefix to RSRV's identity string
---
src/ioc/rsrv/camsgtask.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/ioc/rsrv/camsgtask.c b/src/ioc/rsrv/camsgtask.c
index 16af5bb0d..126bafd80 100644
--- a/src/ioc/rsrv/camsgtask.c
+++ b/src/ioc/rsrv/camsgtask.c
@@ -174,7 +174,7 @@ int casClientInitiatingCurrentThread ( char * pBuf, size_t bufSize )
return RSRV_ERROR;
if ( pBuf && bufSize ) {
- epicsSnprintf(pBuf, bufSize, "%s@%s",
+ epicsSnprintf(pBuf, bufSize, "ca:%s@%s",
pClient->pUserName, pClient->pHostName);
}
return RSRV_OK;
From 6e3e14448ae3099bcee61bb9c78cc9984f524dce Mon Sep 17 00:00:00 2001
From: Andrew Johnson
Date: Wed, 17 Sep 2014 10:12:40 -0500
Subject: [PATCH 6/6] Increase context string to 40 characters.
---
src/ioc/db/dbAccess.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/ioc/db/dbAccess.c b/src/ioc/db/dbAccess.c
index 3856d0edc..5a4b6b613 100644
--- a/src/ioc/db/dbAccess.c
+++ b/src/ioc/db/dbAccess.c
@@ -455,7 +455,7 @@ long dbProcess(dbCommon *precord)
struct rset *prset = precord->rset;
dbRecordType *pdbRecordType = precord->rdes;
unsigned char tpro = precord->tpro;
- char context[20] = "";
+ char context[40] = "";
long status = 0;
int *ptrace;
int set_trace = FALSE;