Files
epics-base/modules/database/src/ioc/db/dbServer.c
2025-03-19 11:03:46 -05:00

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)