183 lines
4.8 KiB
C
183 lines
4.8 KiB
C
/*************************************************************************\
|
|
* Copyright (c) 2014 UChicago Argonne LLC, as Operator of Argonne
|
|
* National Laboratory.
|
|
* SPDX-License-Identifier: EPICS
|
|
* 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 <string.h>
|
|
|
|
#include "dbDefs.h"
|
|
#include "ellLib.h"
|
|
#include "envDefs.h"
|
|
#include "epicsStdio.h"
|
|
|
|
#include "dbServer.h"
|
|
|
|
static ELLLIST serverList = ELLLIST_INIT;
|
|
static enum { registering, initialized, running, paused, stopped }
|
|
state = registering;
|
|
static char *stateNames[] = {
|
|
"registering", "initialized", "running", "paused", "stopped"
|
|
};
|
|
|
|
int dbRegisterServer(dbServer *psrv)
|
|
{
|
|
const char * ignore = envGetConfigParamPtr(&EPICS_IOC_IGNORE_SERVERS);
|
|
ELLNODE *node;
|
|
|
|
if (!psrv || !psrv->name || state != registering)
|
|
return -1;
|
|
|
|
if (strchr(psrv->name, ' ')) {
|
|
fprintf(stderr, "dbRegisterServer: Bad server name '%s'\n",
|
|
psrv->name);
|
|
return -1;
|
|
}
|
|
|
|
if (ignore) {
|
|
size_t len = strlen(psrv->name);
|
|
const char *found;
|
|
while ((found = strstr(ignore, psrv->name))) {
|
|
/* Make sure the name isn't just a substring */
|
|
if ((found == ignore || (found > ignore && found[-1] == ' ')) &&
|
|
(found[len] == 0 || found[len] == ' ')) {
|
|
fprintf(stderr, "dbRegisterServer: Ignoring '%s', per environment\n",
|
|
psrv->name);
|
|
return 0;
|
|
}
|
|
/* It was, try again further down */
|
|
ignore = found + len;
|
|
}
|
|
}
|
|
|
|
for(node=ellFirst(&serverList); node; node = ellNext(node)) {
|
|
dbServer *cur = CONTAINER(node, dbServer, node);
|
|
if(cur==psrv) {
|
|
return 0; /* already registered identically. */
|
|
} else if(strcmp(cur->name, psrv->name)==0) {
|
|
fprintf(stderr, "dbRegisterServer: Can't redefine '%s'.\n", cur->name);
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
ellAdd(&serverList, &psrv->node);
|
|
return 0;
|
|
}
|
|
|
|
int dbUnregisterServer(dbServer *psrv)
|
|
{
|
|
if (state != registering && state != stopped) {
|
|
fprintf(stderr, "dbUnregisterServer: Servers still active!\n");
|
|
return -1;
|
|
}
|
|
if (ellFind(&serverList, &psrv->node) < 0) {
|
|
fprintf(stderr, "dbUnregisterServer: '%s' not registered.\n",
|
|
psrv->name);
|
|
return -1;
|
|
}
|
|
if (state == stopped && psrv->stop == NULL) {
|
|
fprintf(stderr, "dbUnregisterServer: '%s' has no stop() method.\n",
|
|
psrv->name);
|
|
return -1;
|
|
}
|
|
|
|
ellDelete(&serverList, &psrv->node);
|
|
return 0;
|
|
}
|
|
|
|
void dbsr(unsigned level)
|
|
{
|
|
dbServer *psrv = (dbServer *)ellFirst(&serverList);
|
|
|
|
if (!psrv) {
|
|
printf("No server layers registered with IOC\n");
|
|
return;
|
|
}
|
|
|
|
printf("Server state: %s\n", stateNames[state]);
|
|
|
|
while (psrv) {
|
|
printf("Server '%s'\n", psrv->name);
|
|
if (state == running && psrv->report)
|
|
psrv->report(level);
|
|
psrv = (dbServer *)ellNext(&psrv->node);
|
|
}
|
|
}
|
|
|
|
int dbServerClient(char *pBuf, size_t bufSize)
|
|
{
|
|
dbServer *psrv = (dbServer *)ellFirst(&serverList);
|
|
|
|
if (state != running)
|
|
return -1;
|
|
|
|
while (psrv) {
|
|
if (psrv->client &&
|
|
psrv->client(pBuf, bufSize) == 0)
|
|
return 0;
|
|
psrv = (dbServer *)ellNext(&psrv->node);
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
int dbServerStats(const char *name, unsigned *channels, unsigned *clients)
|
|
{
|
|
dbServer *psrv = (dbServer *)ellFirst(&serverList);
|
|
unsigned tch, tcl;
|
|
|
|
if (state != running || !psrv)
|
|
return -1;
|
|
|
|
for (tch = 0, tcl = 0; psrv;
|
|
psrv = (dbServer *)ellNext(&psrv->node)) {
|
|
if (!name) {
|
|
if (psrv->stats) {
|
|
unsigned lch, lcl;
|
|
|
|
psrv->stats(&lch, &lcl);
|
|
tch += lch;
|
|
tcl += lcl;
|
|
}
|
|
continue;
|
|
}
|
|
if (strcmp(name, psrv->name) == 0) {
|
|
if (!psrv->stats)
|
|
return -1;
|
|
|
|
psrv->stats(channels, clients);
|
|
return 0;
|
|
}
|
|
}
|
|
if (!name) {
|
|
if (channels) *channels = tch;
|
|
if (clients) *clients = tcl;
|
|
return 0;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
#define STARTSTOP(routine, method, newState) \
|
|
void routine(void) \
|
|
{ \
|
|
dbServer *psrv = (dbServer *)ellFirst(&serverList); \
|
|
\
|
|
while (psrv) { \
|
|
if (psrv->method) \
|
|
psrv->method(); \
|
|
psrv = (dbServer *)ellNext(&psrv->node); \
|
|
} \
|
|
state = newState; \
|
|
}
|
|
|
|
STARTSTOP(dbInitServers, init, initialized)
|
|
STARTSTOP(dbRunServers, run, running)
|
|
STARTSTOP(dbPauseServers, pause, paused)
|
|
STARTSTOP(dbStopServers, stop, stopped)
|