Something went wrong on our end
-
Alexander Ivanov authored
git-svn-id: https://redoubt.ligo-wa.caltech.edu/svn/advLigoRTS/trunk@3303 6dcd42c9-f523-4c6d-aada-af552506706e
Alexander Ivanov authoredgit-svn-id: https://redoubt.ligo-wa.caltech.edu/svn/advLigoRTS/trunk@3303 6dcd42c9-f523-4c6d-aada-af552506706e
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
testpoint_server.c 60.83 KiB
static char *versionId = "Version $Id$" ;
/*----------------------------------------------------------------------*/
/* */
/* Module Name: testpoint_server */
/* */
/* Module Description: implements server functions for handling the */
/* test point interface */
/* */
/*----------------------------------------------------------------------*/
#ifndef DEBUG
/* Only uncomment this for debugging, do not leave uncommented in a live system */
/*#define DEBUG 3*/
#endif
#define RPC_SVC_FG
#if 0
#ifndef _TESTPOINT_DIRECT
#define _TESTPOINT_DIRECT 0
#endif
#endif
/* Header File List: */
#ifndef __EXTENSIONS__
#define __EXTENSIONS__
#endif
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <errno.h>
#ifdef OS_VXWORKS
#include <vxWorks.h>
#include <semLib.h>
#include <taskLib.h>
#include <taskVarLib.h>
#include <sockLib.h>
#include <inetLib.h>
#include <hostLib.h>
#include <signal.h>
#include <sysLib.h>
#include <timers.h>
#else
#include <sys/types.h>
#include <sys/resource.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
/*#include <netdir.h>*/
#include <unistd.h>
#include <signal.h>
#include <syslog.h>
#include <pthread.h>
#endif
#include "dtt/gdsutil.h"
#include "dtt/rtestpoint.h"
#include "dtt/hardware.h"
#include "dtt/gdschannel.h"
#ifndef _NO_TESTPOINTS
#include "dtt/testpoint.h"
#include "dtt/testpointinfo.h"
#include "dtt/gdssched.h"
#include "dtt/rmorg.h"
#include "dtt/rmapi.h"
#include "dtt/confserver.h"
#endif
#include "PConfig.h"
/*----------------------------------------------------------------------*/
/* */
/* Constants: _KEEPALIVE_TIMEOUT timeout for keep alive signal */
/* _KEEP_AROUND time of keeping an expired client */
/* _CHNNAME_SIZE size of channel name */
/* _TP_MAX_USER max. number of clients/users */
/* _MAX_TPNAMES max. number of tp names in one call */
/* PRM_FILE parameter file name */
/* PRM_SECTION parameter section name */
/* PRM_ENTRY1 entry name for host */
/* PRM_ENTRY2 entry name for rpc prog num */
/* PRM_ENTRY3 entry name for rpc ver num */
/* PRM_ENTRY4 entry name for control system name */
/* _NODE0_LSCX_UNIT_ID unit id of 4K LSC excitation */
/* _NODE0_ASCX_UNIT_ID unit id of 4K ASC excitation */
/* _NODE1_LSCX_UNIT_ID unit id of 2K LSC excitation */
/* _NODE1_ASCX_UNIT_ID unit id of 2K ASC excitation */
/* */
/*----------------------------------------------------------------------*/
#define _KEEPALIVE_TIMEOUT 60
#define _KEEP_AROUND 240
#define _CHNNAME_SIZE MAX_CHNNAME_SIZE
#define _TP_MAX_USER 1000
#define _MAX_TPNAMES 1000
#define PRM_FILE gdsPathFile ("/param", "testpoint.par")
#define PRM_SECTION gdsSectionSite ("node%i")
#define PRM_PRESELECT "preselect%i"
#define PRM_ENTRY1 "hostname"
#define PRM_ENTRY2 "prognum"
#define PRM_ENTRY3 "progver"
#define PRM_ENTRY4 "system"
#ifndef _NO_AWG_CHECK
#define _NODE0_LSCX_UNIT_ID GDS_4k_LSC_EX_ID
#define _NODE0_ASCX_UNIT_ID GDS_4k_ASC_EX_ID
#define _NODE1_LSCX_UNIT_ID GDS_2k_LSC_EX_ID
#define _NODE1_ASCX_UNIT_ID GDS_2k_ASC_EX_ID
#endif
#ifdef RPC_SVC_FG
#define _SVC_FG 1
#else
#define _SFC_FG 0
#endif
#if !defined (OS_VXWORKS) && !defined (PORTMAP)
// NEED FIXING, VERIFICATION
//#define _SVC_MODE RPC_SVC_MT_AUTO
#define _SVC_MODE 0
#else
#define _SVC_MODE 0
#endif
/*----------------------------------------------------------------------*/
/* */
/* Types: tpClient_t client entry (keep alive) */
/* tpUsage_t client (user) id */
/* tpEntry_t internal rep. of a test point */
/* tpNode_t test point node */
/* tpwriter_t info on ddcus which write into tp area */
/* */
/*----------------------------------------------------------------------*/
#ifndef _NO_TESTPOINTS
struct tpClient_t {
/* valid */
int valid;
/* time of last contact */
tainsec_t lastTime;
};
typedef struct tpClient_t tpClient_t;
struct tpUsage_t {
/* time of request */
tainsec_t reqTime;
/* timeout */
tainsec_t timeout;
/* client id */
int clntId;
};
typedef struct tpUsage_t tpUsage_t;
struct tpEntry_t {
/* testpoint ID */
testpoint_t id;
/* in use count */
int inUse;
/* user identification array */
tpUsage_t users[_TP_MAX_USER];
/* channel name of testpint */
char name[_CHNNAME_SIZE];
};
typedef struct tpEntry_t tpEntry_t;
struct tpNode_t {
/* true if node is valid */
int valid;
/* Node number of the node. */
int node ;
/* rpc hostname */
char hostname[80];
/* rpc prog num */
unsigned long prognum;
/* rpc prog ver. */
unsigned long progver;
/* list of preselected testpoints */
testpoint_t preselect[TP_MAX_PRESELECT];
/* list of TP active TPs */
tpEntry_t indx[TP_MAX_INTERFACE][TP_MAX_INDEX];
/* points directly into RM IPC area
rmIpcStr* ipc[TP_MAX_INTERFACE]; */
/* points directly into RM channel info area
dataInfoStr* chninfo[TP_MAX_INTERFACE]; */
/* list of testpoint channel information */
gdsChnInfo_t* tplist;
/* length of list */
int tplistlen;
/* fast lookup table: tp ID -> channel info */
gdsChnInfo_t* tplookup[TP_HIGHEST_INDEX];
};
typedef struct tpNode_t tpNode_t;
#ifndef _NO_AWG_CHECK
typedef struct rmIpcStr rmIpcStr;
struct tpwriter_t {
/* pointer to exc. engine IPC area */
rmIpcStr* IPC;
/* awg alive if true */
int alive;
/* old cycle count */
int oldCycleCount;
};
typedef struct tpwriter_t tpwriter_t;
#endif
/*----------------------------------------------------------------------*/
/* */
/* Globals: sd scheduler */
/* servermux protects globals */
/* initServer if 0 the server is not yet initialized */
/* shutdownflag shutdown flag */
/* tplist list of test points */
/* tpclnts client list with keep alive */
/* tpclntID client ID for clients w/o keep alive */
/* tpwriter information on DCUs writing to tp */
/* */
/*----------------------------------------------------------------------*/
static scheduler_t* sd = NULL;
static mutexID_t servermux;
static int initServer = 0;
static int shutdownflag = 0;
static tpNode_t tpNode ;
static tpClient_t tpclnts[_TP_MAX_USER];
static int tpclntID = _TP_MAX_USER + 1;
#ifndef _NO_AWG_CHECK
static tpwriter_t tpwriter[TP_MAX_INTERFACE];
#endif
#endif
/* Global. Test point manager's node id */
int testpoint_manager_node = -1;
/* Global. Test point manager's RPC program number*/
int testpoint_manager_rpc = -1;
/*----------------------------------------------------------------------*/
/* */
/* Forward declarations: */
/* initTestpointServer initializes testpoint server */
/* finiTestpointServer termionates testpoint server */
/* tpName2Index translate tp names into id numbers */
/* finiTestpointServer cleans up testpoint server */
/* initializeTestpoints sets up testpoint server */
/* cleanupTestpoints garbage collector for test points */
/* updateTestpoints updates testpoints in the refl. mem. */
/* rtestpoint_1 rpc dispatch function */
/* */
/*----------------------------------------------------------------------*/
__init__(initTestpointServer);
#pragma init(initTestpointServer);
__fini__(finiTestpointServer);
#pragma fini(finiTestpointServer);
#ifndef _NO_TESTPOINTS
void setPreselect (int node);
static int tpName2Index (int node, const char* tpNames, TP_r* tp);
static int initializeTestpoints (void);
static int cleanupTestpoints (schedulertask_t* info, taisec_t time,
int epoch, void* arg);
static int updateTestpoints (schedulertask_t* info, taisec_t time,
int epoch, void* arg);
extern void rtestpoint_1 (struct svc_req* rqstp,
register SVCXPRT* transp);
extern int curDaqBlockSize;
#endif
/*----------------------------------------------------------------------*/
/* */
/* Remote Procedure Name: requesttp_1_svc */
/* */
/* Procedure Description: sets test points */
/* */
/* Procedure Arguments: node ID, test point list, timeout */
/* */
/* Procedure Returns: 0 if successful, <0 if not (status) */
/* time and epoch of activation */
/* */
/*----------------------------------------------------------------------*/
bool_t requesttp_1_svc (int id, int node, TP_r tp, quad_t timeout,
resultRequestTP_r* result, struct svc_req* rqstp)
{
#ifdef _NO_TESTPOINTS
result->status = -10;
return TRUE;
#else
int i,j,k; /* index into test point list */
int tpinterface; /* tp interface id */
int len; /* length of test point list */
tpEntry_t* tpp; /* test point entry */
tainsec_t time; /* activation time */
gdsDebug ("request test point");
#ifdef DEBUG
printf ("Request tp id=%d; node=%d; node_valid=%d\n",
id, node, tpNode.valid);
/* JCB */
printf("Request %d testpoint(s)\n", tp.TP_r_len) ;
for (i = 0; i < tp.TP_r_len; i++)
printf("request tp %d\n", tp.TP_r_val[i]) ;
#endif
/* test node ID */
if ((id < 0) || (node < 0) || (node >= TP_MAX_NODE) ||
!tpNode.valid || tpNode.node != node) {
result->status = -2;
return TRUE;
}
/* get server mutex */
MUTEX_GET (servermux);
/* go through supplied test point list */
result->status = 0;
#ifdef DEBUG
printf ("Test point list length is %d\n", tp.TP_r_len);
#endif
// Loop through the list of testpoint to set and check for DAQ overload
int projTpNum = 0; /* Projected test point number */
for (i = 0; i < tp.TP_r_len; i++) {
/* check if ID in list */
if ((tp.TP_r_val[i] <= 0) || (tp.TP_r_val[i] >= TP_HIGHEST_INDEX) || (tpNode.tplookup[tp.TP_r_val[i]] == NULL)) {
continue;
}
/* test whether valid test point */
tpinterface = TP_ID_TO_INTERFACE (tp.TP_r_val[i]);
/* use LSC EXC for DAC channels */
if (tpinterface == TP_DAC_INTERFACE) {
tpinterface = TP_LSC_EX_INTERFACE;
}
len = TP_INTERFACE_TO_INDEX_LEN (tpinterface);
if ((tpinterface < 0) || (tpinterface >= TP_MAX_INTERFACE)) {
continue;
}
/* test whether already in list */
for (j = 0, k = -1; j < len; j++) {
tpp = &tpNode.indx[tpinterface][j];
/* check for duplicate */
if (tpp->id == tp.TP_r_val[i]) {
/* already in list; check in use */
if (tpp->inUse < _TP_MAX_USER) {
tpp->users[tpp->inUse].reqTime = TAInow();
tpp->users[tpp->inUse].timeout = timeout;
tpp->users[tpp->inUse].clntId = id;
// tpp->inUse++;
k = -2;
break;
}
/* too many users */
else {
k = -1;
break;
}
}
if ((k == -1) && (tpp->id == 0)) {
/* found an empty slot */
k = j;
projTpNum++;
}
}
}
/* Check if the total number of testpoint has reached the limit */
{
int tpiface;
int projTpNumNewEntry = -1;
for (tpiface = 0; tpiface < TP_MAX_INTERFACE; tpiface++) {
/* loop over selected test points */
int idxlen = TP_INTERFACE_TO_INDEX_LEN (tpiface);
int tpidx;
for (tpidx = 0; tpidx < idxlen; tpidx++) {
tpEntry_t* tpent; /* test point entry */
tpent = &tpNode.indx[tpiface][tpidx];
if (tpent->id != 0) projTpNum++;
}
}
#ifdef DEBUG
printf("Projected tpnum=%d curDaqSize=%d\n", projTpNum, curDaqBlockSize);
#endif
unsigned int projDaqSize = projTpNum * 4 * 16384 * sys_freq_mult + curDaqBlockSize;
if (projDaqSize > DAQ_DCU_SIZE) {
printf ("Too many testpoints: projected DAQ size %d > %d (maximum)\n", projDaqSize, DAQ_DCU_SIZE);
k = -1;
MUTEX_RELEASE (servermux);
return TRUE;
}
}
for (i = 0; i < tp.TP_r_len; i++) {
/* debug */
#ifdef DEBUG
printf ("Request tp %i\n", tp.TP_r_val[i]);
#endif
/* check if ID in list */
if ((tp.TP_r_val[i] <= 0) ||
(tp.TP_r_val[i] >= TP_HIGHEST_INDEX) ||
(tpNode.tplookup[tp.TP_r_val[i]] == NULL)) {
#ifdef DEBUG
printf ("TP %i not in list\n", tp.TP_r_val[i]);
#endif
continue;
}
/* test whether valid test point */
tpinterface = TP_ID_TO_INTERFACE (tp.TP_r_val[i]);
/* use LSC EXC for DAC channels */
if (tpinterface == TP_DAC_INTERFACE) {
tpinterface = TP_LSC_EX_INTERFACE;
}
len = TP_INTERFACE_TO_INDEX_LEN (tpinterface);
#ifdef DEBUG
printf("Max tp index is %d, tp interface is %d\n", len, tpinterface) ;
printf ("TP %i has interface %d\n", tp.TP_r_val[i], tpinterface);
#endif
if ((tpinterface < 0) || (tpinterface >= TP_MAX_INTERFACE)) {
#ifdef DEBUG
printf ("TP %i has invalid interface %d\n", tp.TP_r_val[i], tpinterface);
#endif
continue;
}
/* test whether already in list */
for (j = 0, k = -1; j < len; j++) {
tpp = &tpNode.indx[tpinterface][j];
/* check for duplicate */
if (tpp->id == tp.TP_r_val[i]) {
/* already in list; check in use */
if (tpp->inUse < _TP_MAX_USER) {
tpp->users[tpp->inUse].reqTime = TAInow();
tpp->users[tpp->inUse].timeout = timeout;
tpp->users[tpp->inUse].clntId = id;
tpp->inUse++;
k = -2;
#ifdef DEBUG
printf ("TP %i already in list; inUse= %d\n", tp.TP_r_val[i], tpp->inUse);
#endif
break;
}
/* too many users */
else {
k = -1;
#ifdef DEBUG
printf ("Too many users\n");
#endif
break;
}
}
if ((k == -1) && (tpp->id == 0)) {
/* found an empty slot */
k = j;
}
}
/* allocate a new test point */
if (k >= 0) {
/* debug */
#ifdef DEBUG
printf ("allocate new TP node/interface/slot %i/%i/%i\n",
node, tpinterface, k);
#endif
tpp = &tpNode.indx[tpinterface][k];
tpp->id = tp.TP_r_val[i];
strncpy (tpp->name,
tpNode.tplookup[tp.TP_r_val[i]]->chName,
_CHNNAME_SIZE);
tpp->name[_CHNNAME_SIZE-1] = 0;
tpp->inUse = 0;
tpp->users[tpp->inUse].reqTime = TAInow();
tpp->users[tpp->inUse].timeout = timeout;
tpp->users[tpp->inUse].clntId = id;
tpp->inUse++;
}
else if (k == -1) {
/* no empty slot or too many users */
result->status = - (i + 1);
break;
}
}
#ifdef DEBUG
printf ("result status = %d\n", result->status);
#endif
/* if failed, cleanup */
if (result->status < 0) {
int ret;
TP_r tpcln;
tpcln.TP_r_len = -result->status;
tpcln.TP_r_val = malloc (tpcln.TP_r_len * sizeof(testpoint_t));
if (tpcln.TP_r_val != 0) {
for (i = 0; i < tpcln.TP_r_len; i++) {
tpcln.TP_r_val[i] = tp.TP_r_val[i];
}
cleartp_1_svc (id, node, tpcln, &ret, rqstp);
}
}
/* release server mutex */
MUTEX_RELEASE (servermux);
/* set activation time */
time = TAInow();
result->time = time / _ONESEC + 1;
if ((time % _ONESEC) / _EPOCH >= TESTPOINT_UPDATE_EPOCH) {
result->time++;
}
result->epoch = 0;
#ifdef DEBUG
printf ("activation time %ld; time now %lld\n", result->time, (long long int) time);
#endif
return TRUE;
#endif
}
/*----------------------------------------------------------------------*/
/* */
/* Remote Procedure Name: requesttpname_1_svc */
/* */
/* Procedure Description: sets test points */
/* */
/* Procedure Arguments: test point names, timeout */
/* */
/* Procedure Returns: 0 if successful, <0 if not (status) */
/* time and epoch of activation */
/* */
/*----------------------------------------------------------------------*/
bool_t requesttpname_1_svc (int id, char* tpNames, quad_t timeout,
resultRequestTP_r* result, struct svc_req* rqstp)
{
#ifdef _NO_TESTPOINTS
result->status = -10;
return TRUE;
#else
int node; /* node number */
TP_r tp; /* list of test points */
gdsDebug ("request test point by name");
printf("Request tp by name %s\n", tpNames) ; /* JCB */
if (tpNode.valid)
{
#ifdef DEBUG
printf ("tp name (node %i) = %s\n", tpNode.node, tpNames);
#endif
/* translate names into test points */
if (tpName2Index (tpNode.node, tpNames, &tp) < 0) {
result->status = -1;
return TRUE;
}
/* request test points */
requesttp_1_svc (id, tpNode.node, tp, timeout, result, rqstp);
free (tp.TP_r_val);
if (result->status < 0) {
result->status = -2;
return TRUE;
}
}
return TRUE;
#endif
}
/*----------------------------------------------------------------------*/
/* */
/* Remote Procedure Name: cleartp_1_svc */
/* */
/* Procedure Description: clears test points */
/* */
/* Procedure Arguments: node ID, test point list */
/* */
/* Procedure Returns: 0 if successful, <0 if not */
/* */
/*----------------------------------------------------------------------*/
bool_t cleartp_1_svc (int id, int node, TP_r tp, int* result,
struct svc_req* rqstp)
{
#ifdef _NO_TESTPOINTS
*result = -10;
return TRUE;
#else
int i,j; /* index into test point list */
int k; /* index into user list */
int tpinterface; /* tp interface id */
int len; /* length of test point list */
tpEntry_t* tpp; /* test point entry */
int clearall; /* clear all */
gdsDebug ("clear test point");
#ifdef DEBUG
printf("Clear test points: len = %d\n", tp.TP_r_len) ;
for (i = 0; i < tp.TP_r_len; i++)
printf("clear tp %d\n", tp.TP_r_val[i]) ; /* JCB */
#endif
/* test node ID */
if ((id < 0) || (node < 0) || (node >= TP_MAX_NODE) ||
!tpNode.valid || tpNode.node != node) {
*result = -2;
return TRUE;
}
/* get server mutex */
MUTEX_GET (servermux);
clearall = 0;
/* go through supplied test point list */
for (i = 0; i < tp.TP_r_len; i++) {
/* debug */
#ifdef DEBUG
printf ("Clear tp %i\n", tp.TP_r_val[i]);
#endif
if (tp.TP_r_val[i] == _TP_CLEAR_ALL) {
/* clear all test points of this node */
memset (tpNode.indx, 0,
TP_MAX_INTERFACE * TP_MAX_INDEX * sizeof (tpEntry_t));
clearall = 1;
break;
}
/* else clear only specific test points */
tpinterface = TP_ID_TO_INTERFACE (tp.TP_r_val[i]);
/* use LSC EXC for DAC channels */
if (tpinterface == TP_DAC_INTERFACE) {
tpinterface = TP_LSC_EX_INTERFACE;
}
len = TP_INTERFACE_TO_INDEX_LEN (tpinterface);
if ((tpinterface < 0) || (tpinterface >= TP_MAX_INTERFACE)) {
continue;
}
/* search through list */
for (j = 0; j < len; j++) {
tpp = &tpNode.indx[tpinterface][j];
if (tpp->id == tp.TP_r_val[i]) {
/* found test point */
for (k = 0; k < tpp->inUse; k++) {
if ((tpp->users[k].clntId == id) &&
(tpp->users[k].timeout <= 0)) {
/* found client identifier */
break;
}
}
/* decrease in use count */
if (k < tpp->inUse) {
tpp->inUse--;
if (tpp->inUse <= 0) {
tpp->id = 0;
}
}
/* shift array */
if (k < tpp->inUse) {
memmove (tpp->users + k, tpp->users + k + 1,
(tpp->inUse - k) * sizeof (tpUsage_t));
}
break;
}
}
}
/* release server mutex */
MUTEX_RELEASE (servermux);
/* check if preselect */
if (clearall) {
setPreselect (node);
}
*result = 0;
return TRUE;
#endif
}
/*----------------------------------------------------------------------*/
/* */
/* Remote Procedure Name: clearnametp_1_svc */
/* */
/* Procedure Description: clears test points by name */
/* */
/* Procedure Arguments: test point names */
/* */
/* Procedure Returns: 0 if successful, <0 if not */
/* */
/*----------------------------------------------------------------------*/
bool_t cleartpname_1_svc (int id, char* tpNames, int* result,
struct svc_req* rqstp)
{
#ifdef _NO_TESTPOINTS
*result = -10;
return TRUE;
#else
int node; /* node number */
TP_r tp; /* list of test points */
gdsDebug ("clear test point by name");
printf("Clear test point by name %s\n", tpNames) ; /* JCB */
/* translate names into test points */
if (tpName2Index (tpNode.node, tpNames, &tp) >= 0)
{
/* clear test points */
cleartp_1_svc (id, tpNode.node, tp, result, rqstp);
free (tp.TP_r_val);
}
*result = 0;
return TRUE;
#endif
}
/*----------------------------------------------------------------------*/
/* */
/* Remote Procedure Name: querytp_1_svc */
/* */
/* Procedure Description: queries test point interface */
/* */
/* Procedure Arguments: request ID, max length of tp list */
/* */
/* Procedure Returns: 0 if successful, <0 if not */
/* test point list */
/* */
/*----------------------------------------------------------------------*/
bool_t querytp_1_svc (int id, int node, int tpinterface, int tplen,
u_long time, int epoch, resultQueryTP_r* result,
struct svc_req* rqstp)
{
#ifdef _NO_TESTPOINTS
memset (result, 0, sizeof (resultQueryTP_r));
result->status = -10;
return TRUE;
#else
gdsDebug ("query test point");
memset (result, 0, sizeof (resultQueryTP_r));
/* debug */
#ifdef DEBUG
printf ("Query node %i interface %i\n", node, tpinterface);
#endif
printf ("Query node %i interface %i\n", node, tpinterface); /* JCB */
/* test node ID */
if ((id < 0) || (node < 0) || (node >= TP_MAX_NODE) ||
!tpNode.valid || tpNode.node != node) {
result->status = -2;
return TRUE;
}
/* allocate memory for result array */
result->tp.TP_r_val = malloc (tplen * sizeof (testpoint_t));
if (result->tp.TP_r_val == NULL) {
result->status = -2;
return FALSE;
}
result->tp.TP_r_len = tplen;
/* fix time if needed */
if (time == 0) {
tainsec_t t = TAInow ();
time = t / _ONESEC;
epoch = (t % _ONESEC) / _EPOCH;
}
/* get index directly from test point client interface */
result->status =
tpGetIndexDirect (node, tpinterface, result->tp.TP_r_val,
result->tp.TP_r_len, time, epoch);
if (result->status >= 0) {
result->tp.TP_r_len = result->status;
}
else {
free (result->tp.TP_r_val);
result->tp.TP_r_val = NULL;
result->tp.TP_r_len = 0;
};
#ifdef DEBUG
{
char buf[256];
tainsec_t now;
now = TAInow();
sprintf (buf, "query test point status (node %i) %i\n",
node, result->status);
sprintf (strend (buf), "req. time = %li : %i\n", time, epoch);
sprintf (strend (buf), "cur. time = %i : %i", (int) (now / _ONESEC),
(int) ((now % _ONESEC + 1000000) / _EPOCH));
gdsDebug (buf);
printf ("%s\n", buf);
if (result->status >= 4) {
printf ("TPs: %i %i %i %i\n", result->tp.TP_r_val[0],
result->tp.TP_r_val[1], result->tp.TP_r_val[2],
result->tp.TP_r_val[3]);
}
}
#endif
return TRUE;
#endif
}
/*----------------------------------------------------------------------*/
/* */
/* Remote Procedure Name: keepalive_1_svc */
/* */
/* Procedure Description: keep alive function */
/* This function is used as follows: Clients which do not support a */
/* keep alive call it once during initializationwith the value -2; */
/* the function returns a handle greater than the max. index of the */
/* client list. Clients which support a keep alive call this function */
/* once during initialization with the value -1; and then every 15s */
/* with the returned handle from the first call. In this case the */
/* the returned handle is an index into the client list. If the function*/
/* is not called fro more than 60s, all test points associated with this*/
/* handle are deleted. A negative return value indicates an error */
/* and the client should shut down. Client list entries which have */
/* expired are kept around for another 240s before they are deleted. */
/* */
/* Procedure Arguments: request ID, return status, service */
/* */
/* Procedure Returns: 0 if successful, <0 if not */
/* */
/*----------------------------------------------------------------------*/
bool_t keepalive_1_svc (int id, int* ret, struct svc_req* rqstp)
{
int i; /* index into client list */
struct in_addr addr; /* client address */
#ifdef DEBUG
char buf[256];
rpcGetClientaddress (rqstp->rq_xprt, &addr);
sprintf (buf, "keep alive %i from %s", id, inet_ntoa (addr));
gdsDebug (buf);
printf ("%s\n", buf);
#endif
MUTEX_GET (servermux);
if (id < -1) {
*ret = tpclntID++;
}
else if (id < 0) {
rpcGetClientaddress (rqstp->rq_xprt, &addr);
for (i = 0; i < _TP_MAX_USER; i++) {
/* look for free id */
if (!tpclnts[i].valid) {
tpclnts[i].valid = 1;
tpclnts[i].lastTime = TAInow();
*ret = i;
MUTEX_RELEASE (servermux);
{
time_t now = time (NULL);
#ifdef DEBUG
printf ("Allocate new TP handle %i by %s at %s\n",
i, inet_ntoa (addr), ctime (&now));
#endif
fflush(stdout);
}
return TRUE;
}
}
printf ("Failed to allocate TP handle by %s\n",
inet_ntoa (addr));
*ret = -1;
}
else if ((id >= _TP_MAX_USER) || (!tpclnts[id].valid)) {
*ret = -1;
}
else {
tpclnts[id].lastTime = TAInow();
*ret = id;
}
MUTEX_RELEASE (servermux);
return TRUE;
}
/*----------------------------------------------------------------------*/
/* */
/* External Procedure Name: rtestpoint_1_freeresult */
/* */
/* Procedure Description: frees memory of rpc call */
/* */
/* Procedure Arguments: rpc transport info, xdr routine for result, */
/* pointer to result */
/* */
/* Procedure Returns: TRUE if successful, FALSE if failed */
/* */
/*----------------------------------------------------------------------*/
int rtestpoint_1_freeresult (SVCXPRT* transp,
xdrproc_t xdr_result, caddr_t result)
{
(void) xdr_free (xdr_result, result);
return TRUE;
}
#ifndef _NO_TESTPOINTS
/*----------------------------------------------------------------------*/
/* */
/* Internal Procedure Name: setPreselect */
/* */
/* Procedure Description: set preselected TPs */
/* */
/* Procedure Arguments: node */
/* */
/* Procedure Returns: void */
/* */
/*----------------------------------------------------------------------*/
void setPreselect (int node)
{
resultRequestTP_r result; /* result from request */
TP_r tp; /* TP list */
int k; /* index */
/* initialize TP list */
tp.TP_r_len = 0;
tp.TP_r_val = malloc (2 * TP_MAX_PRESELECT * sizeof (short));
/* select TPs */
for (k = 0; k < TP_MAX_PRESELECT; ++k) {
if (tpNode.preselect[k] > 0) {
tp.TP_r_val[tp.TP_r_len++] = tpNode.preselect[k];
#ifdef DEBUG
printf("Preselecting %d on node %d\n", tpNode.preselect[k], node);
#endif
}
}
if (tp.TP_r_len > 0) {
requesttp_1_svc (0x7fffffff, node, tp, 0, &result, 0);
}
free (tp.TP_r_val);
}
/*----------------------------------------------------------------------*/
/* */
/* Internal Procedure Name: tpName2Index */
/* */
/* Procedure Description: translates test point names into id numbers */
/* */
/* Procedure Arguments: node, test point names, test point list */
/* */
/* Procedure Returns: 0 if successful, <0 if not (status) */
/* */
/*----------------------------------------------------------------------*/
static int tpName2Index (int node, const char* tpNames, TP_r* tp)
{
char* buf; /* name buffer */
char* p; /* cursor into buffer */
gdsChnInfo_t chn; /* channel info structure */
int tp_node; /* node of test point name */
char * saveptr;
/* allocate memory */
buf = malloc (strlen (tpNames) + 2);
tp->TP_r_val = malloc (_MAX_TPNAMES * sizeof (testpoint_t));
if ((tp->TP_r_val == NULL) || (buf == NULL)) {
free (buf);
free (tp->TP_r_val);
return -1;
}
tp->TP_r_len = 0;
strcpy (buf, tpNames);
/* go through name list */
p = strtok_r (buf, " ,\t\n", &saveptr);
while ((p != NULL) && (tp->TP_r_len < _MAX_TPNAMES)) {
printf("tpName2Index checking %s\n", p);
if ((gdsChannelInfo (p, &chn) == 0) &&
(tpIsValid (&chn, &tp_node, tp->TP_r_val + tp->TP_r_len)) &&
(node == tp_node)) {
printf ("%s is tp %i (node %i)\n", p,
tp->TP_r_val[tp->TP_r_len],
tp_node);
tp->TP_r_len++;
}
printf("node=%d; tp_node=%d\n", node, tp_node);
p = strtok_r (NULL, " \t\n", &saveptr);
}
free (buf);
return 0;
}
/*----------------------------------------------------------------------*/
/* */
/* Internal Procedure Name: cleanupTestpoints */
/* */
/* Procedure Description: garbage collector for test points */
/* */
/* Procedure Arguments: scheduler task, time, epoch, void* */
/* */
/* Procedure Returns: 0 if successful, <0 if not */
/* */
/*----------------------------------------------------------------------*/
static int cleanupTestpoints (schedulertask_t* info, taisec_t time,
int epoch, void* arg)
{
int i; /* index into test point list */
int j; /* interface ID */
int k; /* index into usage array */
int len; /* length of test point list */
tpEntry_t* tpp; /* test point entry */
tainsec_t t; /* current time */
int remove; /* true if tp is obsolete */
t = (tainsec_t) time * _ONESEC + (tainsec_t) epoch * _EPOCH;
if (tpNode.valid)
{
/* loop over interfaces */
for (j = 0; j < TP_MAX_INTERFACE; j++) {
/* get server mutex */
MUTEX_GET (servermux);
/* loop over selected test points */
len = TP_INTERFACE_TO_INDEX_LEN (j);
for (i = 0; i < len; i++) {
tpp = &tpNode.indx[j][i];
if (tpp->id == 0) {
continue;
}
/* loop over clients */
for (k = 0; k < tpp->inUse; k++) {
remove = 0;
/* check time out */
if ((tpp->users[k].timeout > 0) &&
(tpp->users[k].reqTime + tpp->users[k].timeout < t)) {
/* found old testpoint */
/* printf ("remove tp %i (node %i) because of timeout\n",
tpp->id, tpNode.node);*/
remove = 1;
}
#if 0
/* Disable keepalive feature at LASTI (for now) */
/* check keep alive */
if ((tpp->users[k].clntId >= 0) &&
(tpp->users[k].clntId < _TP_MAX_USER) &&
((!tpclnts[tpp->users[k].clntId].valid) ||
(tpclnts[tpp->users[k].clntId].lastTime +
_KEEPALIVE_TIMEOUT * _ONESEC < t))) {
/* printf ("remove tp %i (node %i) because of keep alive\n",
tpp->id, tpNode.node);
printf ("client id = %i\n", tpp->users[k].clntId);
printf ("client is %svalid\n",
(tpclnts[tpp->users[k].clntId].valid) ? "" : "not ");
printf ("last time = %f\n", (double)
tpclnts[tpp->users[k].clntId].lastTime / _ONESEC);
printf ("cur. time = %f\n", (double) t / _ONESEC);*/
remove = 1;
}
#endif
/* remove entry if obsolete */
if (remove) {
/* decrease in use count */
tpp->inUse--;
if (tpp->inUse <= 0) {
tpp->id = 0;
}
/* shift array */
if (k < tpp->inUse) {
memmove (tpp->users + k, tpp->users + k + 1,
(tpp->inUse - k) * sizeof (tpUsage_t));
}
}
}
}
/* release server mutex */
MUTEX_RELEASE (servermux);
}
}
/* loop over client interface */
for (k = 0; k < _TP_MAX_USER; k++) {
/* if expired keep it around for a while than delete it */
if ((tpclnts[k].valid) &&
(tpclnts[k].lastTime + _KEEPALIVE_TIMEOUT * _ONESEC < t)) {
if (++tpclnts[k].valid > _KEEP_AROUND) {
tpclnts[k].valid = 0;
}
}
}
return 0;
}
/*----------------------------------------------------------------------*/
/* */
/* Internal Procedure Name: updateTestpoints */
/* */
/* Procedure Description: updates test points in refl. memory */
/* */
/* Procedure Arguments: scheduler task, time, epoch, void* */
/* */
/* Procedure Returns: 0 if successful, <0 if not */
/* */
/*----------------------------------------------------------------------*/
static int updateTestpoints (schedulertask_t* info, taisec_t time,
int epoch, void* arg)
{
int i; /* index into test point list */
int j; /* interface ID */
int size; /* size of test point array */
int len; /* length of test point list */
tpEntry_t* tpp; /* test point entry */
testpoint_t tp[TP_MAX_INDEX];/* test point index */
char tpchn[TP_MAX_INDEX][_CHNNAME_SIZE];
/* test point channel names */
tainsec_t t; /* current time */
int addr; /* RM address of tp index */
#if 0
printf ("update %li/%i\n", time, epoch);
#endif
t = (tainsec_t) time * _ONESEC + (tainsec_t) epoch * _EPOCH;
if (tpNode.valid)
{
/* loop over interfaces */
for (j = 0; j < TP_MAX_INTERFACE; j++) {
/* get server mutex */
MUTEX_GET (servermux);
/* make index */
len = TP_INTERFACE_TO_INDEX_LEN (j);
memset (tp, 0, len * sizeof (testpoint_t));
for (i = 0, size = 0; i < len; i++) {
tpp = &tpNode.indx[j][i];
/* copy index entry */
if (tpp->id != 0) {
tp[size] = tpp->id;
strncpy (tpchn[size], tpp->name, _CHNNAME_SIZE);
tpchn[size][_CHNNAME_SIZE-1] = 0;
}
else {
tp[size] = 0;
strcpy (tpchn[size], "");
}
#if 0
// print first four test point numbers and channel names
if (size < 4) printf (" %d tp = %s; tpnum = %d\n", size, tpchn[size], tp[size]);
#endif
size++;
}
/* release server mutex */
MUTEX_RELEASE (servermux);
#if 0
if ((j == 0)) {
printf ("node = %i, interface = %i - ", tpNode.node, j);
printf ("tp = %i %i %i %i %i\n", tp[0],tp[1],tp[2],tp[3],tp[4]);
}
#endif
#if 0
// TODO: this seems to clobber my test point numbers
/* disable excitation test points if awg not running */
#ifndef _NO_AWG_CHECK
if (!tpwriter[tpNode.node][j].alive) {
#ifdef DEBUG
printf ("AWG not alive: clear all TPs\n");
#endif
memset (tp, 0, len * sizeof (testpoint_t));
}
#endif
#endif
#ifndef __linux__
#error
/* swap on little-endian machines */
i = 0;
*(char*)&i = 1;
if (i == 1) {
if (len % 2 == 1) { /* add a point if odd length */
tp[len++] = 0;
}
for (i = 0; i < len; i += 2) {
testpoint_t temp = tp[i];
tp[i] = tp[i+1]; tp[i+1] = temp;
/* tp[i] = ((tp[i]&0xFF)<<8) | ((tp[i]&0xFF00)>>8); */
}
}
#endif
/* write index to reflective memory */
addr = TP_NODE_INTERFACE_TO_INDEX_OFFSET (tpNode.node, j);
if ((len <= 0) || (addr <= 0)) {
continue;
}
/* debug */
#if 0
printf ("write tps %i %i %i from node %i to 0x%x\n",
tp[0], tp[1], tp[2],
TP_NODE_ID_TO_RFM_ID (tpNode.node), addr);
#endif
#if RMEM_LAYOUT > 0
if (rmWrite (TP_NODE_ID_TO_RFM_ID (tpNode.node), (char*) tp, addr,
len * sizeof (testpoint_t), 0) != 0) {
gdsError (GDS_ERR_PROG, "RM1 write failure");
}
#if 0
printf("rmWrite(0, %x %x %d )\n", tp, addr, len * sizeof (testpoint_t));
#endif
#if 0
#if TARGET != (TARGET_L1_GDS_AWG1 + 20) && TARGET != (TARGET_L1_GDS_AWG1 + 21)
if (rmWrite (1 + TP_NODE_ID_TO_RFM_ID (tpNode.node), (char*) tp, addr,
len * sizeof (testpoint_t), 0) != 0) {
gdsError (GDS_ERR_PROG, "RM2 write failure");
}
#endif
#endif
#else
if (rmWrite (TP_NODE_ID_TO_RFM_ID (tpNode.node), (char*) tp, addr,
len * sizeof (testpoint_t), 0) != 0) {
gdsError (GDS_ERR_PROG, "RM write failure");
}
#endif
/* write channel information into reflective memory
for (i = 0; i < size; i++) {
strncpy ((tpNode.chninfo[j] + i)->chName,
tpchn[i], MAX_CHNNAME_SIZE - 1);
}
tpNode.ipc[j]->channelCount = size;*/
}
}
return 0;
}
#ifndef _NO_AWG_CHECK
/*----------------------------------------------------------------------*/
/* */
/* Internal Procedure Name: awgAlive */
/* */
/* Procedure Description: tests if awg is alive */
/* */
/* Procedure Arguments: scheduler task, time, epoch, void* */
/* */
/* Procedure Returns: 0 if successful, <0 if not */
/* */
/*----------------------------------------------------------------------*/
static int awgAlive (schedulertask_t* info, taisec_t time,
int epoch, void* arg)
{
int j; /* tp interface index */
int cycleCount; /* current cycle count */
for (j = 0; j < TP_MAX_INTERFACE; j++) {
if (tpwriter[j].IPC == NULL) {
tpwriter[j].alive = 0;
continue;
}
cycleCount = tpwriter[j].IPC->cycle;
tpwriter[j].alive =
(cycleCount != tpwriter[j].oldCycleCount);
tpwriter[j].oldCycleCount = cycleCount;
}
return 0;
}
#endif
#endif
#ifndef _NO_TESTPOINTS
/*----------------------------------------------------------------------*/
/* */
/* Internal Procedure Name: initializeTestpoints */
/* */
/* Procedure Description: initializes server stuff */
/* */
/* Procedure Arguments: void */
/* */
/* Procedure Returns: 0 if successful, <0 if failed */
/* */
/*----------------------------------------------------------------------*/
static int initializeTestpoints (void)
{
schedulertask_t task; /* update task entry */
#ifndef _NO_AWG_CHECK
int node; /* node index */
int j; /* tp interface index */
#endif
/* quit if already initiaized */
if (initServer == 2) {
return 0;
}
/* test if low level init */
if (initServer == 0) {
initTestpointServer();
if (initServer == 0) {
return -1;
}
}
/* fill in pointers of ddcu's which write to tp area */
#ifndef _NO_AWG_CHECK
memset (tpwriter, 0, sizeof (tpwriter));
for (j = 0; j < TP_MAX_INTERFACE; j++) {
/* determine unit id of awg dcu */
int unitID;
int base;
int size;
int rfmid;
/* determine base address and size of awg dcu */
/* We don't know the node number, but it doesn't
* matter for advanced LIGO. Pick a value no 0 or 1.
*/
unitID = TP_NODE_INTERFACE_TO_UNIT_ID (20, j);
base = UNIT_ID_TO_RFM_OFFSET (unitID);
size = UNIT_ID_TO_RFM_SIZE (unitID);
rfmid = 0;
printf("interface %d: unitID = %d, base = %d, size = %d\n", j, unitID, base, size) ;
/* set IPC pointer if valid dcu */
if ((base >= 0) && (rmCheck (rfmid, base, size))) {
tpwriter[j].IPC =
(rmIpcStr*) (rmBaseAddress (rfmid) + base);
}
else {
tpwriter[j].IPC = NULL;
}
/* reset alive flag */
tpwriter[j].alive = 0;
}
#endif
/* make sure heartbeat is installed */
if (installHeartbeat (NULL) < 0) {
return -2;
}
/* init scheduler */
sd = createScheduler (0, NULL, NULL);
if (sd == NULL) {
return -3;
}
/* setup task info structure of update task */
SET_TASKINFO_ZERO (&task);
task.flag = SCHED_REPEAT | SCHED_WAIT;
task.waittype = SCHED_WAIT_IMMEDIATE;
task.repeattype = SCHED_REPEAT_INFINITY;
task.repeatratetype = SCHED_REPEAT_EPOCH;
task.repeatrate = NUMBER_OF_EPOCHS;
task.synctype = SCHED_SYNC_EPOCH;
task.syncval = TESTPOINT_UPDATE_EPOCH;
task.func = updateTestpoints;
/* schedule update task */
if (scheduleTask (sd, &task) < 0) {
closeScheduler (sd, 3 * _EPOCH);
sd = NULL;
return -4;
}
/* setup task info structure of awg alive task */
#ifndef _NO_AWG_CHECK
SET_TASKINFO_ZERO (&task);
task.flag = SCHED_REPEAT | SCHED_WAIT;
task.waittype = SCHED_WAIT_IMMEDIATE;
task.repeattype = SCHED_REPEAT_INFINITY;
task.repeatratetype = SCHED_REPEAT_EPOCH;
task.repeatrate = 2;
task.synctype = SCHED_SYNC_EPOCH;
task.syncval = 1;
task.func = awgAlive;
/* schedule awg alive task */
if (scheduleTask (sd, &task) < 0) {
closeScheduler (sd, 3 * _EPOCH);
sd = NULL;
return -4;
}
#endif
/* setup task info structure of cleanup task */
SET_TASKINFO_ZERO (&task);
task.flag = SCHED_REPEAT | SCHED_WAIT;
task.waittype = SCHED_WAIT_IMMEDIATE;
task.repeattype = SCHED_REPEAT_INFINITY;
task.repeatratetype = SCHED_REPEAT_EPOCH;
task.repeatrate = NUMBER_OF_EPOCHS;
task.synctype = SCHED_SYNC_EPOCH;
task.syncval = 1;
task.func = cleanupTestpoints;
/* schedule cleanup task */
if (scheduleTask (sd, &task) < 0) {
closeScheduler (sd, 3 * _EPOCH);
sd = NULL;
return -4;
}
/* intialize test point client interface */
if (testpoint_client() < 0) {
closeScheduler (sd, 3 * _EPOCH);
sd = NULL;
return -5;
}
initServer = 2;
return 0;
}
/*----------------------------------------------------------------------*/
/* */
/* Internal Procedure Name: isTestpoint */
/* */
/* Procedure Description: returns true if channel is a test point */
/* */
/* Procedure Arguments: channel info */
/* */
/* Procedure Returns: true if yes, false if no */
/* */
/*----------------------------------------------------------------------*/
static int _query_node = 0; /* rm ID of query */
static int isTestpoint (const gdsChnInfo_t* info)
{
return IS_TP (info) && (info->rmId == _query_node);
}
#endif
/*----------------------------------------------------------------------*/
/* */
/* External Procedure Name: testpoint_server */
/* */
/* Procedure Description: start rpc service task for test points */
/* */
/* Procedure Arguments: void */
/* */
/* Procedure Returns: does not return if successful, <0 otherwise */
/* */
/*----------------------------------------------------------------------*/
int testpoint_server (void)
{
#ifdef _NO_TESTPOINTS
printf ("test point interface disabled\n");
gdsWarningMessage ("test point interface disabled");
return -1;
#else
int j; /* tp interface index */
int rpcpmstart; /* port monitor flag */
SVCXPRT* transp; /* service transport */
int proto; /* protocol */
char remotehost[PARAM_ENTRY_LEN];
/* remote hostname */
char section[30]; /* section name */
char param[30]; /* paramter name */
struct in_addr addr; /* host address */
struct in_addr laddr; /* local address */
unsigned long prognum; /* rpc prog. num. */
unsigned long progver; /* rpc prog. ver. */
unsigned long presel; /* preselected tp */
int node; /* node id */
int n; /* node id */
int k; /* index */
int rmNode; /* RM node ID */
int duplicate; /* duplicate prog num/ver */
int reg; /* # of registered services */
int tp; /* tp index */
static confServices conf[TP_MAX_NODE];
/* configuration service */
static int confnum; /* # of conf entries */
static char confbuf[1024]; /* configuration buffer */
char* pConf; /* conf pointer */
struct in_addr host; /* local host address */
char sysname[PARAM_ENTRY_LEN];
extern char system_name[PARAM_ENTRY_LEN];
#ifdef OS_VXWORKS
rpcTaskInit();
#endif
/* initialize test points */
if (initializeTestpoints() < 0) {
printf("unable to initialize test points\n");
gdsError (GDS_ERR_PROG, "unable to initialize test points");
return -1;
}
/* Mark the node as invalid until it's found in the parameter file. */
tpNode.valid = 0 ;
for (node = 0; node < TP_MAX_NODE; node++) {
/*printf("tpman checking node %d\n", node);*/
rmNode = 0;
if (rmBaseAddress (rmNode) == NULL) {
printf("reflective memory pointer not set\n");
continue;
}
/* make section header */
sprintf (section, "%s-node%i", site_prefix, node);
/* get remote host from parameter file */
strcpy (remotehost, "");
loadStringParam (PRM_FILE, section, PRM_ENTRY1,
remotehost);
// Skip unconfigured section
if (strcmp (remotehost, "") == 0) continue;
printf ("remotehost = %s; section= %s\n", remotehost, section);
if (rpcGetHostaddress (remotehost, &addr) != 0) {
printf("Cannot resolve hostname \"%s\"\n", remotehost);
continue;
}
loadStringParam (PRM_FILE, section, PRM_ENTRY4, sysname);
printf ("sysname = %s\n", sysname);
if (sysname[0] == 0) continue; /* Mandatory field */
/* Determine if this is my node */
if ((rpcGetLocaladdress (&laddr) < 0) ||
(addr.s_addr != laddr.s_addr) ||
strcmp(sysname, system_name)) {
printf ("this is not my node %x %x %s\n", addr.s_addr, laddr.s_addr, system_name);
continue;
}
printf ("this is my node\n");
inet_ntoa_b (addr, tpNode.hostname);
prognum = RPC_PROGNUM_TESTPOINT;
progver = RPC_PROGVER_TESTPOINT;
#if 0
// Do not load from the config file
/* get rpc parameters from parameter file */
loadNumParam (PRM_FILE, section, PRM_ENTRY2, &prognum);
loadNumParam (PRM_FILE, section, PRM_ENTRY3, &progver);
#endif
// Use GDS node to generate a unique RPC number
prognum += node;
tpNode.prognum = prognum;
tpNode.progver = progver;
memset (tpNode.indx, 0, TP_MAX_INTERFACE * TP_MAX_INDEX * sizeof (tpEntry_t));
/* Mark the node as valid and record the node number. */
tpNode.valid = 1 ;
tpNode.node = node ;
/* get preselected testpoints */
for (k = 0; k < TP_MAX_PRESELECT; ++k) {
sprintf (param, PRM_PRESELECT, k);
presel = 0;
loadNumParam (PRM_FILE, section, param, &presel);
if ((presel > 0) && (presel < TP_HIGHEST_INDEX)) {
tpNode.preselect[k] = presel;
printf("Preselecting testpoint %ld on node %d\n", presel, node);
}
else {
tpNode.preselect[k] = 0;
}
}
/* Since the node has been found, stop looking. */
break ;
}
/* load channel information */
if (!tpNode.valid) {
printf("Failed to find my node in %s\n", PRM_FILE);
exit(1);
} else {
/* query length of channel info list of the specified node */
MUTEX_GET (servermux);
_query_node = node;
tpNode.tplistlen = gdsChannelListLen (-1, isTestpoint);
printf("Channel list length for node %d is %d\n", node, tpNode.tplistlen);
if (tpNode.tplistlen <= 0) {
tpNode.tplistlen = 0;
MUTEX_RELEASE (servermux);
}
else
{
/* allocate memory for list */
tpNode.tplist = malloc (tpNode.tplistlen * sizeof (gdsChnInfo_t));
if (tpNode.tplist == NULL) {
tpNode.tplistlen = 0;
MUTEX_RELEASE (servermux);
return -2;
}
/* load list */
tpNode.tplistlen = gdsChannelList (-1, isTestpoint, tpNode.tplist, tpNode.tplistlen);
MUTEX_RELEASE (servermux);
if (tpNode.tplistlen <= 0) {
free (tpNode.tplist);
tpNode.tplistlen = 0;
tpNode.tplist = NULL;
}
else
{
/* build lookup table */
memset (tpNode.tplookup, 0, sizeof (tpNode.tplookup));
for (j = 0; j < tpNode.tplistlen; j++) {
tp = tpNode.tplist[j].chNum;
if ((tp > 0) && (tp < TP_HIGHEST_INDEX)) {
tpNode.tplookup[tp] = tpNode.tplist + j;
/* printf ("node %i tp %i = %s\n", node, tp,
tpNode.tplookup[tp]->chName);*/
}
}
}
}
}
/* clear memory */
/* loop through interfaces */
for (j = 0; j < TP_MAX_INTERFACE; j++) {
char* a = rmBaseAddress (TP_NODE_ID_TO_RFM_ID(tpNode.node)) +
TP_NODE_INTERFACE_TO_DATA_OFFSET(tpNode.node, j);
#ifdef OS_SOLARIS
/* Would get a system crash on Solaris with memset() */
{
int k;
int l = DATA_BLOCKS * TP_NODE_INTERFACE_TO_DATA_BLOCKSIZE(tpNode.node, j);
for (k = 0; k < l; k++) a[k] = 0;
}
#else
memset (a, 0, DATA_BLOCKS *
TP_NODE_INTERFACE_TO_DATA_BLOCKSIZE(tpNode.node, j));
#endif
}
if (tpNode.valid) {
setPreselect (tpNode.node);
}
/* get local address */
confnum = 0;
if (rpcGetLocaladdress (&host) < 0) {
gdsError (GDS_ERR_PROG, "unable to obtain local address");
return -3;
}
/* init rpc services */
if (rpcInitializeServer (&rpcpmstart, _SVC_FG, _SVC_MODE,
&transp, &proto) < 0) {
gdsError (GDS_ERR_PROG, "unable to start rpc service");
return -4;
}
/* register with rpc service */
if (rpcRegisterService (rpcpmstart, transp, proto,
tpNode.prognum, tpNode.progver, rtestpoint_1) != 0)
{
gdsError (GDS_ERR_PROG,
"unable to register test point service");
return -6;
}
printf ("Test point manager (%lx / %li): node %i\n",
tpNode.prognum, tpNode.progver, node) ;
/* Set the global variable value for the testpoint_manager_node */
testpoint_manager_node = node;
testpoint_manager_rpc = tpNode.prognum;
/* add configuration info */
if (confnum == 0) {
pConf = confbuf;
conf[0].id = 0;
conf[0].answer = stdAnswer;
conf[0].user = confbuf;
confnum++;
}
else {
pConf = strend (confbuf);
strcpy (pConf, "\n");
pConf++;
}
sprintf (pConf, "tp %i 0 %s %ld %ld", node,
inet_ntoa (host), tpNode.prognum, tpNode.progver);
/* announce service */
if (conf_server (conf, confnum, 1) < 0) {
gdsWarningMessage ("unable to start configuration services");
}
/* start server */
rpcStartServer (rpcpmstart, &shutdownflag);
/* never reached */
return -8;
#endif
}
/*----------------------------------------------------------------------*/
/* */
/* Internal Procedure Name: initTestpointServer */
/* */
/* Procedure Description: initializes test point server */
/* */
/* Procedure Arguments: void */
/* */
/* Procedure Returns:void */
/* */
/*----------------------------------------------------------------------*/
static void initTestpointServer (void)
{
#ifndef _NO_TESTPOINTS
if (initServer != 0) {
return;
}
/* First call, log version ID */
printf("testpoint_server %s\n", versionId) ;
/* create server mutex */
if (MUTEX_CREATE (servermux) != 0) {
return;
}
/* reset test point data memory */
memset (&tpNode, 0, sizeof (tpNode));
memset (tpclnts, 0, sizeof (tpclnts));
/* set initServer and return */
shutdownflag = 1;
initServer = 1;
#endif
}
/*----------------------------------------------------------------------*/
/* */
/* Internal Procedure Name: finiTestpointServer */
/* */
/* Procedure Description: cleans up test point server */
/* */
/* Procedure Arguments: void */
/* */
/* Procedure Returns:void */
/* */
/*----------------------------------------------------------------------*/
static void finiTestpointServer (void)
{
int node; /* node ID */
#ifndef _NO_TESTPOINTS
if (initServer == 0) {
return;
}
/* destroy server mutex */
if (MUTEX_DESTROY (servermux) != 0) {
return;
}
/* close scheduler */
if (sd != NULL) {
closeScheduler (sd, 0); /* timeout must be zero in exit routine */
sd = NULL;
}
/* free memory */
if (tpNode.valid && (tpNode.tplist != NULL)) {
free (tpNode.tplist);
}
/* set initServer and return */
shutdownflag = 0;
initServer = 0;
#endif
}