1058 lines
36 KiB
C
1058 lines
36 KiB
C
#define ident "1A05"
|
|
/*---------------------------------------------------------------------------*/
|
|
#ifdef __DECC
|
|
#pragma module SINQHM_CTRL ident
|
|
#endif
|
|
/*
|
|
** Link_options - Here is the Linker Option File
|
|
**! sinqhm_ctrl
|
|
**! sinq_olb/lib/inc=deltat_messages
|
|
**!!
|
|
**!! To build SINQHM_CTRL on LNSA09
|
|
**!!
|
|
**!! $ import tasmad
|
|
**!! $ define/job deltat_c_tlb sinq_c_tlb
|
|
**!! $ sss := ud0:[maden.pss123.wind.sinqhm]
|
|
**!! $ bui 'sss'sinqhm_ctrl debug
|
|
** Link_options_end
|
|
**
|
|
** Building on Alpha OSF/1:
|
|
**
|
|
cc -std1 -g -o ~/bin/sinqhm_ctrl -I/public/lib/include \
|
|
-transitive_link -L/public/lib -lsinq -lrt \
|
|
~/SinqHM/sinqhm_ctrl.c
|
|
**
|
|
** +--------------------------------------------------------------+
|
|
** | Paul Scherrer Institute |
|
|
** | Computing Section |
|
|
** | |
|
|
** | This software may be used freely by non-profit organizations.|
|
|
** | It may be copied provided that the name of P.S.I. and of the |
|
|
** | author is included. Neither P.S.I. nor the author assume any |
|
|
** | responsibility for the use of this software outside of P.S.I.|
|
|
** +--------------------------------------------------------------+
|
|
**
|
|
** Module Name . . . . . . . . : [...HMSR]SINQHM_CTRL.C
|
|
**
|
|
** Author . . . . . . . . . . : D. Maden
|
|
** Date of creation . . . . . . : Dec 1996
|
|
**
|
|
** Purpose
|
|
** =======
|
|
** SINQHM_CTRL.C is an Internet Client which can be used to send control
|
|
** messages to a front-end processor running the SINQHM histogram
|
|
** memory server process. Control messages may be sent to configure,
|
|
** de-configure, rundown, set the level of debug printing, start data
|
|
** acquisition, stop data acquisition, show the status of SINQHM_SRV, or
|
|
** zero the histogram memory.
|
|
**
|
|
** 1) Configure:
|
|
** =========
|
|
** The configuration information is obtained from the logical name
|
|
** table. The following logical name definitions are used ...
|
|
**
|
|
** SINQHM_FRONTEND "<node> <port> <pkt_size>"
|
|
** <node> is the node where SINQHM_SRV is running,
|
|
** <port> is SINQHM_SRV's TCP/IP port number (dflt=2400),
|
|
** <pkt_size> is max packet size for send/rcve (dflt = 8192).
|
|
** SINQHM_NHISTS The number of histograms (dflt = 1).
|
|
** SINQHM_NBINS The number of bins per histogram (no dflt).
|
|
** SINQHM_BINWID The number of bytes per bin (dflt = 4).
|
|
**
|
|
** Once the configuration information has been obtained from the logical
|
|
** names, a connection is made to the SINQHM_SRV root process on the
|
|
** front-end and a configure message is sent. SINQHM_SRV will check the
|
|
** information, start up a child process, FILLER, which will do the work of
|
|
** filling histograms, and then send a reply.
|
|
**
|
|
** Note: If SINQHM_SRV has already been successfully configured, i.e. it
|
|
** already has an active FILLER child process, it must be
|
|
** de-configured first.
|
|
**
|
|
** 2) Debug:
|
|
** ======
|
|
** The level of debug printing in the SINQHM_SRV root process can be set. The
|
|
** higher the level, the more print-out on the front-end processor's console
|
|
** occurs. The debug level is inherited by any server children (or FILLER)
|
|
** which subsequently get started.
|
|
**
|
|
** 3) De-configure:
|
|
** ============
|
|
** "De-configuration" involves terminating any child processes of the
|
|
** SINQHM_SRV root process. Normally, it is expected that the server children
|
|
** will have been terminated via the protocol between the servers and their
|
|
** clients so that a de-configure involves simply the termination of FILLER.
|
|
** This is a so-called "gentle" de-configure. However, in order to facilitate
|
|
** the recovery from error situations, it is possible to specify a "harsh"
|
|
** de-configure in which any active server children will also be terminated.
|
|
** A gentle de-configure will fail if there are active children.
|
|
**
|
|
** 4) Rundown:
|
|
** =======
|
|
** "Rundown" implies the termination not only of the SINQHM_SRV children but
|
|
** also of the root process itself. Once a rundown has been performed,
|
|
** intervention will be required on the front-end (e.g. reboot or creation
|
|
** of a new SINQHM_SRV root job from the front-end console) before SINQHM_SRV
|
|
** can be used again.
|
|
**
|
|
** 5) Show-Status:
|
|
** ===========
|
|
** The status of SINQHM_SRV is illicited and printed out.
|
|
**
|
|
** 6) Start-Data-Acquisition
|
|
** ======================
|
|
** The SinqHM-Filler process in the HM is instructed to start data-acq.
|
|
**
|
|
** 7) Stop-Data-Acquisition
|
|
** =====================
|
|
** The SinqHM-Filler process in the HM is instructed to stop data-acq.
|
|
**
|
|
** 8) Zero:
|
|
** ====
|
|
** The complete histogram area is set to zero.
|
|
**
|
|
** Use:
|
|
** ===
|
|
** Define the foreign command:
|
|
**
|
|
** $ sinqhm_ctrl :== $mad_exe:sinqhm_ctrl
|
|
**
|
|
** Then issue the command:
|
|
**
|
|
** $ sinqhm_ctrl <cmnd> <modifier>
|
|
**
|
|
** where <cmnd> may be "CONFIG", "DEBUG", "DECONFIG", "GO", "HELP",
|
|
** "RUNDOWN", "SHOW", "STOP" or "ZERO". If <cmnd> is omitted or none of
|
|
** the above or if any error occurs obtaining the configuration
|
|
** information for the "CONFIG" command, a "HELP" command will be assumed.
|
|
**
|
|
** For the "CONFIG" command, <modifier> may be specified as "SUSPEND".
|
|
** If so, the filler task in the front-end will suspend as soon as it
|
|
** starts so that it can be debugged.
|
|
**
|
|
** For the "DEBUG" command, <modifier> is an integer specifying the debug
|
|
** level. <modifier> may also be specified as "ON" or "OFF", corresponding
|
|
** to levels 1 and 0 respectively. If <modifier> is anything else (or
|
|
** absent), "ON" is assumed.
|
|
**
|
|
** For the "DECONFIG" command, <modifier> is used to specify the
|
|
** "harshness" of the de-configure. If <modifier> is specified as
|
|
** "HARSH", the de-configure will be "harsh". If <modifier> is anything
|
|
** else (or absent) the de-configure will be gentle.
|
|
**
|
|
** Communication between SINQHM_CTRL and the server is via TCP/IP protocol.
|
|
**
|
|
** Updates:
|
|
** 1A01 18-Dec-1996 DM. Initial version.
|
|
**====================================================================
|
|
*/
|
|
#include <errno.h>
|
|
#include <netdb.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <time.h>
|
|
|
|
#include <netinet/in.h>
|
|
#include <arpa/inet.h>
|
|
|
|
#include <ctype.h>
|
|
#include <math.h>
|
|
#include <sys/socket.h>
|
|
#include <string.h>
|
|
#include <sys/types.h>
|
|
|
|
/*
|
|
**==================== Global Definitions =====================================
|
|
*/
|
|
#include "sinq_prototypes.h"
|
|
#include "sinqhm_def.h"
|
|
|
|
#define SUCCESS 1
|
|
#define ERROR 0
|
|
#define NIL '\0'
|
|
|
|
#define HM_SIZE 65536 /* Number of Bins in Hist Mem */
|
|
/*
|
|
**==================== Some functions and structures =====================
|
|
**
|
|
** Fixed-Length Descriptor:
|
|
*/
|
|
struct dsc__descriptor_s {
|
|
unsigned short dsc__w_length; /* length of data item in bytes */
|
|
unsigned char dsc__b_dtype; /* data type code */
|
|
unsigned char dsc__b_class; /* descriptor class code */
|
|
char *dsc__a_pointer; /* address of data storage */
|
|
};
|
|
/*
|
|
**==================== Global Variables ======================================
|
|
*/
|
|
int My_errno, My_vaxc_errno;
|
|
|
|
struct req_buff_struct Req_buff;
|
|
struct rply_buff_struct Rply_buff;
|
|
|
|
char Rmt_node[10];
|
|
int Rmt_port;
|
|
int Pkt_size;
|
|
|
|
int Hm_mode; /* The histogramming mode */
|
|
int Nhists; /* The number of histograms to fill */
|
|
int Lo_bin; /* The first bin */
|
|
int Nbins; /* The number of bins to fill */
|
|
int Binwid; /* The number of bytes per bin */
|
|
int Compress; /* The bin compression factor */
|
|
|
|
struct dsc__descriptor_s Name_desc;
|
|
|
|
extern int C_gbl_status; /* Return status from C_... routines */
|
|
/*
|
|
**=============================================================================
|
|
** Local routines.
|
|
**
|
|
** get_SINQHM_FRONTEND : Extract info from SINQHM_FRONTEND environment variable
|
|
** show_help : Display the help text.
|
|
** strMatch : Match 2 strings.
|
|
**----------------------------------------------------------------------------
|
|
** Prototypes
|
|
*/
|
|
int getenv_integer (char *name, int *value, int dflt_value);
|
|
void get_SINQHM_FRONTEND (char *node, int node_l, char *node_dflt,
|
|
int *port, int port_dflt,
|
|
int *pktlen, int pktlen_dflt);
|
|
void show_help (char *modifier);
|
|
int strMatch (char *str1, char *str2);
|
|
/*
|
|
**--------------------------------------------------------------------------*/
|
|
int getCheckStatusResponse (
|
|
/* ======================
|
|
** Wait for the status response from SinqHM and
|
|
** check it for errors.
|
|
**
|
|
*/ int skt, /* The socket for recv */
|
|
struct rply_buff_struct *reply, /* The buffer to use */
|
|
int rlen) { /* Size of buffer */
|
|
|
|
int status;
|
|
|
|
status = recv (skt, (char *) reply, rlen, 0);
|
|
if (status == -1) {
|
|
FailInet ("\n\007SINQHM_CTRL -- recv error");
|
|
return ERROR;
|
|
} else if (status != rlen) {
|
|
printf ("\007"
|
|
"SINQHM_CTRL -- recv error - unexpected byte count: %d/%d\n",
|
|
rlen, status);
|
|
return ERROR;
|
|
}
|
|
if (ntohl (reply->bigend) != 0x12345678) {
|
|
printf ("\007"
|
|
"SINQHM_CTRL -- big-endian/little-endian problem!\n"
|
|
" Buffer received in non-network byte order!\n");
|
|
return ERROR;
|
|
}
|
|
status = ntohl (reply->status);
|
|
if (status == KER__SUCCESS) {
|
|
return SUCCESS;
|
|
}else if (status == KER__BAD_CREATE) {
|
|
printf ("\007 Status response is KER__BAD_CREATE\n");
|
|
printf (" Sub-status = %d\n", ntohl (reply->sub_status));
|
|
}else if (status == KER__BAD_STATE) {
|
|
printf ("\007 Status response is KER__BAD_STATE\n");
|
|
}else if (status == KER__BAD_VALUE) {
|
|
printf ("\007 Status response is KER__BAD_VALUE\n");
|
|
}else if (status == KER__BAD_RECV) {
|
|
printf ("\007 Status response is KER__BAD_RECV\n");
|
|
}else if (status == KER__BAD_ALLOC) {
|
|
printf ("\007 Status response is KER__BAD_ALLOC\n");
|
|
}else {
|
|
printf ("\007 Bad and unrecognised status response: 0x%x\n",
|
|
status);
|
|
}
|
|
if (reply->u.message[0] != NIL) {
|
|
printf (" Message = \"%s\"\n", &reply->u.message[0]);
|
|
}
|
|
return ERROR;
|
|
}
|
|
/*
|
|
**--------------------------------------------------------------------------*/
|
|
int getenv_integer (char *name, int *value, int dflt_value) {
|
|
/* ==============
|
|
** Extract an integer from an
|
|
** environment variable.
|
|
*/
|
|
char *p_env;
|
|
|
|
p_env = getenv (name); /* Get pointer to env var */
|
|
if (p_env == NULL) {
|
|
/* Env. var. not found, return default */
|
|
*value = dflt_value;
|
|
return EXIT_FAILURE;
|
|
}else { /* Convert it to binary */
|
|
if (sscanf (p_env, "%d", value) != 1) {
|
|
*value = dflt_value; /* Value is not integer, return default */
|
|
return EXIT_FAILURE;
|
|
}else {
|
|
return EXIT_SUCCESS;
|
|
}
|
|
}
|
|
}
|
|
/*
|
|
**--------------------------------------------------------------------------*/
|
|
void get_SINQHM_FRONTEND (
|
|
/* ===================
|
|
** Extract info from the SINQHM_FRONTEND
|
|
** environment variable.
|
|
**
|
|
*/ char *node, int node_l, char *node_dflt,
|
|
int *port, int port_dflt,
|
|
int *pktlen, int pktlen_dflt) {
|
|
|
|
int env_len;
|
|
char *p_env, *token;
|
|
char my_env[100];
|
|
|
|
p_env = getenv ("SINQHM_FRONTEND"); /* Get pointer to env var */
|
|
if (p_env == NULL) {
|
|
/* Env. var. not found, return defaults */
|
|
StrJoin (node, node_l, node_dflt, "");
|
|
*port = port_dflt;
|
|
*pktlen = pktlen_dflt;
|
|
}else { /* Make a local copy of it in case the original is in ..
|
|
** .. read-protected memory (strtok needs to be able to ..
|
|
** .. modify it */
|
|
env_len = sizeof (my_env);
|
|
StrEdit (my_env, p_env, "uncomment compress trim", &env_len);
|
|
token = (env_len == 0) ? NULL : strtok (my_env, " ,"); /* Get node token */
|
|
if ((token == NULL) || (token[0] == ' ')) {
|
|
/* Node token not found, return defaults */
|
|
StrJoin (node, node_l, node_dflt, "");
|
|
*port = port_dflt;
|
|
*pktlen = pktlen_dflt;
|
|
}else {
|
|
StrJoin (node, node_l, token, "");
|
|
token = strtok (NULL, " ,"); /* Get port token */
|
|
if (token == NULL) {
|
|
*port = port_dflt; /* Port token not found, return defaults */
|
|
*pktlen = pktlen_dflt;
|
|
}else {
|
|
if (sscanf (token, "%d", port) != 1) {
|
|
*port = port_dflt; /* Port token illegal, return defaults */
|
|
*pktlen = pktlen_dflt;
|
|
}else {
|
|
token = strtok (NULL, " ,"); /* Get packet-size token */
|
|
if (token == NULL) {
|
|
*pktlen = pktlen_dflt; /* Packet-size token not found, use dflt */
|
|
}else {
|
|
if (sscanf (token, "%d", pktlen) != 1) {
|
|
*pktlen = pktlen_dflt; /* Packet-size token illegal, use dflt */
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
/*
|
|
**--------------------------------------------------------------------------*/
|
|
void show_help (char *modifier) {
|
|
/* =========
|
|
*/
|
|
int len;
|
|
|
|
len = strlen (modifier);
|
|
if (len == 0) goto sh_basic;
|
|
|
|
if (strMatch (modifier, "CONFIG") >= 1) goto sh_config;
|
|
if (strMatch (modifier, "DEBUG") >= 3) goto sh_debug;
|
|
if (strMatch (modifier, "DECONFIG") >= 3) goto sh_deconfig;
|
|
if (strMatch (modifier, "GO") >= 1) goto sh_go;
|
|
if (strMatch (modifier, "RUNDOWN") >= 1) goto sh_rundown;
|
|
if (strMatch (modifier, "SETUP") >= 2) goto sh_setup;
|
|
if (strMatch (modifier, "SHOW") >= 1) goto sh_show;
|
|
if (strMatch (modifier, "STOP") >= 2) goto sh_stop;
|
|
if (strMatch (modifier, "ZERO") >= 1) goto sh_zero;
|
|
|
|
sh_basic:
|
|
printf ("\n"
|
|
" The following commands are recognised by SINQHM_CTRL:\n"
|
|
" CONFIG <mode> - configure the hist memory.\n"
|
|
" DEBUG <level> - sets the debug level.\n"
|
|
" DECONFIG <harshness> - de-configure the hist memory.\n"
|
|
" GO - start data acquisition.\n"
|
|
" HELP <subject> - generate help text.\n"
|
|
" RUNDOWN - run down SinqHM server.\n"
|
|
" SHOW - get status of hist memory.\n"
|
|
" STOP - stop data acquisition.\n"
|
|
" ZERO - zero the HM buffer.\n"
|
|
"\n"
|
|
" In order to use SINQHM_CTRL on a VMS system, a \"foreign command\" must\n"
|
|
" be defined, e.g:\n"
|
|
" $ ctrl :== $mad_exe:sinqhm_ctrl\n"
|
|
"\n"
|
|
" To get more help, issue the command: ctrl help <subject>\n"
|
|
"\n"
|
|
" where <subject> may be any of\n"
|
|
"\n"
|
|
" CONFIG DEBUG DECONFIG GO RUNDOWN\n"
|
|
" Setup SHOW STOP ZERO\n"
|
|
"\n");
|
|
return;
|
|
|
|
sh_setup:
|
|
printf ("\nSetup:\n"
|
|
"\n"
|
|
" The histogram memory with which SINQHM_CTRL is to communicate is\n"
|
|
" specified on Unix systems via an environment variable, thus:\n"
|
|
"\n"
|
|
" setenv SINQHM_FRONTEND \"<host> <port> <pkt-size>\"\n"
|
|
"\n"
|
|
" In addition, the following environment variables are used by CONFIG\n"
|
|
"\n"
|
|
" setenv SINQHM_HM_MODE <mode> (Dflt = SQHM__HM_DIG)\n"
|
|
" setenv SINQHM_NHISTS <nhists> (Dflt = 1)\n"
|
|
" setenv SINQHM_LOW_BIN <lo_bin> (Dflt = 0)\n"
|
|
" setenv SINQHM_NBINS <nbins> (Dflt = none)\n"
|
|
" setenv SINQHM_BINWID <binwid> (Dflt = 4)\n"
|
|
" setenv SINQHM_COMPRESS <cmprs> (Dflt = 0)\n"
|
|
"\n"
|
|
" On VMS systems, logical names are used instead, e.g.\n"
|
|
"\n"
|
|
" define/group sinqhm_frontend \"<host> <port> <pkt-size>\"\n"
|
|
" define/group sinqhm_hm_mode <mode>\n"
|
|
"\n"
|
|
" Defaults: <host> = None <port> = 2400 <pkt-size> = 8192\n"
|
|
"\n");
|
|
return;
|
|
|
|
sh_config:
|
|
printf ("\n"
|
|
" CONFIG <mode> - configure the hist memory.\n"
|
|
"\n"
|
|
" See \"help setup\" for a list of the environment variables which may be\n"
|
|
" used for specifying the configuration parameters.\n"
|
|
"\n"
|
|
" The filler process in the hist memory will be started.\n"
|
|
"\n"
|
|
" If <mode> is specified as \"SUSPEND\", the filler process will\n"
|
|
" immediately enter a suspended state so that it can be debugged.\n"
|
|
"\n");
|
|
return;
|
|
|
|
sh_debug:
|
|
printf ("\n"
|
|
" Debug:\n"
|
|
"\n"
|
|
" DEBUG <level> - sets the level of debug messages to the\n"
|
|
" hist memory console.\n"
|
|
"\n"
|
|
" <level> may be \"OFF\", \"ON\", 0, 1, 2 or 3.\n"
|
|
"\n"
|
|
" \"OFF\" is equivalent to 0\n"
|
|
" \"ON\" is equivalent to 1\n"
|
|
" The default is \"ON\".\n"
|
|
"\n");
|
|
return;
|
|
|
|
sh_deconfig:
|
|
printf ("\n"
|
|
" Deconfig:\n"
|
|
"\n"
|
|
" DECONFIG <harshness> - de-configure the hist memory.\n"
|
|
"\n"
|
|
" If <harshness> is not specified, there must be no active clients\n"
|
|
" for the command to be accepted.\n"
|
|
"\n"
|
|
" If <harshness> is specified as \"HARSH\", any active clients will\n"
|
|
" be killed.\n"
|
|
"\n"
|
|
" The filler task is also terminated.\n"
|
|
"\n");
|
|
return;
|
|
|
|
sh_go:
|
|
printf ("\n"
|
|
" Go:\n"
|
|
"\n"
|
|
" GO - start data acquisition by SinqHM-filler\n"
|
|
"\n"
|
|
" An SQHM_DAQ/DAQ__GO command will be sent to SinqHM-master to cause\n"
|
|
" SinqHM-filler to start data acquisition.\n"
|
|
"\n");
|
|
return;
|
|
|
|
sh_rundown:
|
|
printf ("\n"
|
|
" Rundown:\n"
|
|
"\n"
|
|
" USE WITH CAUTION\n"
|
|
" ================\n"
|
|
"\n"
|
|
" RUNDOWN - runs down SinqHM\n"
|
|
"\n"
|
|
" SinqHM-master, SinqHM-filler and all SinqHM-servers will\n"
|
|
" be terminated.\n"
|
|
"\n"
|
|
" After issuing this command, manual intervention on the\n"
|
|
" histogram memory will be necessary in order to restart\n"
|
|
" SinqHM.\n"
|
|
"\n");
|
|
return;
|
|
|
|
sh_show:
|
|
printf ("\n"
|
|
" Show:\n"
|
|
"\n"
|
|
" SHOW - get and display the status of the hist memory.\n"
|
|
"\n");
|
|
return;
|
|
|
|
sh_stop:
|
|
printf ("\n"
|
|
" Stop:\n"
|
|
"\n"
|
|
" STOP - stop data acquisition by SinqHM-filler\n"
|
|
"\n"
|
|
" An SQHM_DAQ/DAQ__STOP command will be sent to SinqHM-master to cause\n"
|
|
" SinqHM-filler to stop data acquisition.\n"
|
|
"\n");
|
|
return;
|
|
|
|
sh_zero:
|
|
printf ("\n"
|
|
" Zero:\n"
|
|
"\n"
|
|
" ZERO - zero the histogram memory buffer\n"
|
|
"\n"
|
|
" An SQHM_ZERO command will be sent to SinqHM-master. The values of\n"
|
|
" hist_no, first_bin and n_bins will be set to -1 so that the entire\n"
|
|
" histogram memory buffer will be set to zero.\n"
|
|
"\n");
|
|
return;
|
|
}
|
|
/*
|
|
**--------------------------------------------------------------------------*/
|
|
int strMatch (char *str1, char *str2) {
|
|
/* ========
|
|
** See if str1 matches str2. Case is ignored.
|
|
** The length of str1 must be less than or equal to the
|
|
** length of str2.
|
|
** Return zero if no match, otherwise the length of str1.
|
|
*/
|
|
int i = 0;
|
|
|
|
while ((tolower (str1[i]) == tolower (str2[i])) && (str1[i] != '\0')) i++;
|
|
if (str1[i] != '\0') i = 0;
|
|
|
|
return i;
|
|
}
|
|
/*
|
|
**==========================================================================
|
|
**
|
|
** Main line program
|
|
** ------------------
|
|
**==========================================================================*/
|
|
main (int argc, char *argv[]) {
|
|
/*==========================================================================*/
|
|
int i, j, k, status;
|
|
int is1, is2;
|
|
char *p_addr, tmp_ch;
|
|
char *cmnd, *modifier, buff[8];
|
|
unsigned int daq_state_now;
|
|
unsigned int daq_state_was;
|
|
unsigned int filler_mask;
|
|
int cnct_skt; /* Connect socket */
|
|
int rw_skt; /* Read/write socket */
|
|
struct sockaddr_in lcl_sockname;
|
|
struct sockaddr_in rmt_sockname;
|
|
int rmt_inet_addr;
|
|
struct in_addr *rmt_inet_addr_pntr;
|
|
struct hostent *rmt_hostent;
|
|
int rmt_sockname_len;
|
|
/*============================================================================*/
|
|
printf ("\n SinqHM_Ctrl Ident %s.", ident);
|
|
/*============================================================================
|
|
** Analyse the arguments to see what has to be done.
|
|
*/
|
|
if (argc > 1) { /* First arg is <cmnd> */
|
|
cmnd = argv[1];
|
|
for (i = 0; i < strlen (cmnd); i++) { /* Convert to upper case */
|
|
cmnd[i] = toupper (cmnd[i]);
|
|
}
|
|
if (cmnd[0] == '-') cmnd++; /* Ignore a leading "-" (i.e. get .. */
|
|
/* .. ready for porting to UNIX */
|
|
}else {
|
|
cmnd = "?";
|
|
}
|
|
if ((strMatch (cmnd, "CONFIG") == 0) &&
|
|
(strMatch (cmnd, "DEBUG") < 3) &&
|
|
(strMatch (cmnd, "DECONFIG") < 3) &&
|
|
(strMatch (cmnd, "GO") == 0) &&
|
|
(strMatch (cmnd, "RUNDOWN") < 7) &&
|
|
(strMatch (cmnd, "HELP") == 0) &&
|
|
(strMatch (cmnd, "?") == 0) &&
|
|
(strMatch (cmnd, "SHOW") == 0) &&
|
|
(strMatch (cmnd, "STOP") < 2) &&
|
|
(strMatch (cmnd, "ZERO") == 0)) cmnd = "HELP";
|
|
|
|
if (argc > 2) { /* Second arg is <modifier> */
|
|
modifier = argv[2];
|
|
for (i = 0; i < strlen (modifier); i++) { /* Convert to upper case */
|
|
modifier[i] = toupper (modifier[i]);
|
|
}
|
|
}else {
|
|
modifier = "";
|
|
}
|
|
if (strMatch (cmnd, "HELP") != 0) goto help;
|
|
if (strMatch (cmnd, "?") != 0) goto help;
|
|
/*============================================================================
|
|
** Start out by finding the TCP/IP location of SINQHM_SRV and making
|
|
** a connection to it. Any errors during this phase cause the program
|
|
** to exit with an error status.
|
|
*/
|
|
get_SINQHM_FRONTEND (Rmt_node, sizeof (Rmt_node), "",
|
|
&Rmt_port, PORT_BASE,
|
|
&Pkt_size, 8192);
|
|
if (Rmt_node[0] == NIL) {
|
|
printf ("\n");
|
|
modifier = "SETUP";
|
|
show_help (modifier);
|
|
printf ("\007\n"
|
|
" The histogram memory is not defined correctly.\n"
|
|
"\n"
|
|
" If this is a UNIX system, check that the environment variable\n"
|
|
" \"SINQHM_FRONTEND\" is defined correctly.\n"
|
|
"\n"
|
|
" If this is a VMS system, check that the logical name "
|
|
"\"SINQHM_FRONTEND\" is\n"
|
|
" defined correctly.\n"
|
|
"\n");
|
|
return EXIT_FAILURE;
|
|
}
|
|
/*
|
|
** Get Internet address of the front-end.
|
|
*/
|
|
rmt_hostent = gethostbyname (Rmt_node);
|
|
if (rmt_hostent == NULL) {
|
|
for (i = 0; i < strlen (Rmt_node); i++)
|
|
Rmt_node[i] = toupper (Rmt_node[i]);
|
|
if (strcmp (Rmt_node, "SQFE01") == 0) {
|
|
rmt_inet_addr_pntr = (struct in_addr *) &rmt_inet_addr;
|
|
rmt_inet_addr = inet_addr ("129.129.56.181");
|
|
} else {
|
|
printf ("Server Node is %s.\n", Rmt_node);
|
|
FailInet ("\nGethostbyname error.");
|
|
}
|
|
} else {
|
|
rmt_inet_addr_pntr = (struct in_addr *) rmt_hostent->h_addr_list[0];
|
|
}
|
|
printf (" Server is %s ", Rmt_node);
|
|
printf ("(%s),", inet_ntoa (*rmt_inet_addr_pntr));
|
|
printf (" Port %d.\n", Rmt_port);
|
|
/*
|
|
** Create a TCP/IP socket for connecting to SINQHM_SRV root and bind it.
|
|
*/
|
|
cnct_skt = socket (AF_INET, SOCK_STREAM, 0);
|
|
if (cnct_skt == -1) FailInet ("\nSocket error.");
|
|
|
|
lcl_sockname.sin_family = AF_INET;
|
|
lcl_sockname.sin_port = htons (0);
|
|
lcl_sockname.sin_addr.s_addr = 0;
|
|
status = bind (cnct_skt, (struct sockaddr *) &lcl_sockname,
|
|
sizeof (lcl_sockname));
|
|
if (status == -1) FailInet ("\nBind error.");
|
|
/*
|
|
** Connect to SINQHM_SRV root.
|
|
*/
|
|
rmt_sockname_len = sizeof (rmt_sockname);
|
|
rmt_sockname.sin_family = AF_INET;
|
|
rmt_sockname.sin_port = htons (Rmt_port);
|
|
rmt_sockname.sin_addr.s_addr = rmt_inet_addr_pntr->s_addr;
|
|
status = connect (cnct_skt, (struct sockaddr *) &rmt_sockname,
|
|
sizeof (rmt_sockname));
|
|
if (status == -1) {
|
|
GetErrno (&My_errno, &My_vaxc_errno);
|
|
FailInet ("\nConnect error");
|
|
}
|
|
/*============================================================================
|
|
** Switch according to value of <cmnd>
|
|
*/
|
|
if (strMatch (cmnd, "CONFIG") > 0) goto config;
|
|
if (strMatch (cmnd, "DEBUG") >= 3) goto debug;
|
|
if (strMatch (cmnd, "DECONFIG") >= 3) goto deconfig;
|
|
if (strMatch (cmnd, "GO") > 0) goto go;
|
|
if (strMatch (cmnd, "RUNDOWN") == 7) goto rundown;
|
|
if (strMatch (cmnd, "STOP") >= 2) goto stop;
|
|
if (strMatch (cmnd, "ZERO") > 0) goto zero;
|
|
goto show;
|
|
/*============================================================================*/
|
|
config:
|
|
/*====== Configure - Extract values from the logical names.
|
|
*/
|
|
getenv_integer ("SINQHM_HM_MODE", &Hm_mode, SQHM__HM_DIG);
|
|
getenv_integer ("SINQHM_NHISTS", &Nhists, 1);
|
|
getenv_integer ("SINQHM_LOW_BIN", &Lo_bin, 0);
|
|
is1 = getenv_integer ("SINQHM_NBINS", &Nbins, 0);
|
|
getenv_integer ("SINQHM_BINWID", &Binwid, 4);
|
|
getenv_integer ("SINQHM_COMPRESS", &Compress, 0);
|
|
if (is1 != EXIT_SUCCESS) {
|
|
printf ("\n\007 SINQHM setup is not defined or not complete.\n");
|
|
printf (" Here is some help ...\n");
|
|
show_help ("SETUP");
|
|
if (is1 != EXIT_SUCCESS) {
|
|
printf (" The problem is with SINQHM_NBINS\n");
|
|
}
|
|
printf ("\n");
|
|
close (cnct_skt);
|
|
return EXIT_FAILURE;
|
|
}
|
|
/*
|
|
** Set up and send the configure message.
|
|
*/
|
|
if (strMatch (modifier, "SUSPEND") >= 3) {
|
|
Hm_mode |= SQHM__DEBUG;
|
|
}
|
|
|
|
Req_buff.bigend = htonl (0x12345678);
|
|
Req_buff.cmnd = htonl (SQHM_CONFIG);
|
|
|
|
Req_buff.u.cnfg.mode = htonl (Hm_mode);
|
|
Req_buff.u.cnfg.n_hists = htonl (Nhists);
|
|
Req_buff.u.cnfg.lo_bin = htonl (Lo_bin);
|
|
Req_buff.u.cnfg.num_bins = htonl (Nbins);
|
|
Req_buff.u.cnfg.binwid = htonl (Binwid);
|
|
Req_buff.u.cnfg.compress = htonl (Compress);
|
|
|
|
printf (" Configuration:\n"
|
|
" Histogramming mode is 0x%08x\n", Hm_mode);
|
|
printf (" Number of histograms = %5d\n"
|
|
" Index of first bin = %5d\n"
|
|
" Number of bins per histogram = %5d\n"
|
|
" Number of bytes per bin = %5d\n"
|
|
" Bin compression factor = %5d\n",
|
|
Nhists, Lo_bin, Nbins, Binwid, Compress);
|
|
if ((Hm_mode & SQHM__DEBUG) != 0)
|
|
printf ("\007\n Warning -- SQHM__DEBUG suspend flag is set!\n\n");
|
|
printf (" Configuring ...");
|
|
|
|
status = send (cnct_skt, (char *) &Req_buff, sizeof (Req_buff), 0);
|
|
if (status == -1) FailInet ("\nSINQHM_CTRL -- send error");
|
|
if (status != sizeof (Req_buff)) {
|
|
printf ("\nSINQHM_CTRL -- wrong number of bytes sent: %d", status);
|
|
return EXIT_FAILURE;
|
|
}
|
|
/*
|
|
** Wait for the status response.
|
|
*/
|
|
status = getCheckStatusResponse (cnct_skt, &Rply_buff, sizeof (Rply_buff));
|
|
if (status == SUCCESS) {
|
|
printf (" done.\n");
|
|
}
|
|
/*
|
|
** Close the connection.
|
|
*/
|
|
status = close (cnct_skt);
|
|
if ((status != 0) && (errno != ECONNRESET))
|
|
FailInet ("\nSINQHM_CTRL -- close error");
|
|
return EXIT_SUCCESS;
|
|
/*============================================================================*/
|
|
debug:
|
|
/*===== Debug. Set up the debug level of the front-end..
|
|
*/
|
|
Req_buff.bigend = htonl (0x12345678);
|
|
Req_buff.cmnd = htonl (SQHM_DBG);
|
|
if (strcmp (modifier, "ON") == 0) { /* "modifier" may be "ON", "OFF" ..
|
|
** .. or an integer. */
|
|
Req_buff.u.dbg.level = htonl (1); /* Turn on, level 1 */
|
|
printf (" Setting SinqHM debug level on (1) ...");
|
|
}else if (strcmp (modifier, "OFF") == 0) {
|
|
Req_buff.u.dbg.level = 0; /* Turn off, level 0 */
|
|
printf (" Setting SinqHM debug level off (0) ...");
|
|
}else if (strcmp (modifier, "") == 0) {
|
|
Req_buff.u.dbg.level = htonl (1); /* Turn on, level 1 */
|
|
printf (" \"DEBUG ON\" assumed ..."
|
|
" setting SinqHM debug level = 1 ...");
|
|
}else {
|
|
status = sscanf (modifier, "%i", &i);
|
|
status = sscanf (modifier, "%i", &Req_buff.u.dbg.level);
|
|
if (status == 1) {
|
|
Req_buff.u.dbg.level = htonl (i);
|
|
printf (" Setting SinqHM debug level = %d ...", i);
|
|
}else {
|
|
Req_buff.u.dbg.level = htonl (1); /* Turn on, if error */
|
|
printf (" Invalid DEBUG command. \"DEBUG ON\" assumed ...");
|
|
}
|
|
}
|
|
status = send (cnct_skt, (char *) &Req_buff, sizeof (Req_buff), 0);
|
|
if (status == -1) FailInet ("\nSINQHM_CTRL -- send error");
|
|
if (status != sizeof (Req_buff)) {
|
|
printf ("SINQHM_CTRL -- wrong number of bytes sent: %d", status);
|
|
return EXIT_FAILURE;
|
|
}
|
|
/*
|
|
** Wait for the status response.
|
|
*/
|
|
status = getCheckStatusResponse (cnct_skt, &Rply_buff, sizeof (Rply_buff));
|
|
if (status == SUCCESS) {
|
|
printf (" done.\n");
|
|
}
|
|
/*
|
|
** Close the connection.
|
|
*/
|
|
status = close (cnct_skt);
|
|
if ((status != 0) && (errno != ECONNRESET))
|
|
FailInet ("\nSINQHM_CTRL -- close error");
|
|
return EXIT_SUCCESS;
|
|
/*============================================================================*/
|
|
deconfig:
|
|
/*======== De-configure. Set up and send the deconfig message.
|
|
*/
|
|
Req_buff.bigend = htonl (0x12345678);
|
|
Req_buff.cmnd = htonl (SQHM_DECONFIG);
|
|
Req_buff.u.decnfg.sub_code = 0; /* Be gentle, by default */
|
|
if (strcmp (modifier, "HARSH") == 0) {
|
|
Req_buff.u.decnfg.sub_code = htonl (1); /* But be harsh, if ordered */
|
|
printf (" Deconfiguring (mit Gewalt!) ...");
|
|
}else {
|
|
printf (" Deconfiguring ...");
|
|
}
|
|
|
|
status = send (cnct_skt, (char *) &Req_buff, sizeof (Req_buff), 0);
|
|
if (status == -1) FailInet ("\nSINQHM_CTRL -- send error");
|
|
if (status != sizeof (Req_buff)) {
|
|
printf ("SINQHM_CTRL -- wrong number of bytes sent: %d", status);
|
|
return EXIT_FAILURE;
|
|
}
|
|
/*
|
|
** Wait for the status response.
|
|
*/
|
|
status = getCheckStatusResponse (cnct_skt, &Rply_buff, sizeof (Rply_buff));
|
|
if (status == SUCCESS) {
|
|
printf (" done.\n");
|
|
}
|
|
/*
|
|
** Close the connection.
|
|
*/
|
|
status = close (cnct_skt);
|
|
if ((status != 0) && (errno != ECONNRESET))
|
|
FailInet ("\nSINQHM_CTRL -- close error");
|
|
return EXIT_SUCCESS;
|
|
/*============================================================================*/
|
|
go:
|
|
/*== Go. Get SinqHM-filler to start taking data.
|
|
*/
|
|
printf (" Starting data acquisition ...");
|
|
|
|
Req_buff.bigend = htonl (0x12345678);
|
|
Req_buff.cmnd = htonl (SQHM_DAQ);
|
|
Req_buff.u.daq.sub_cmnd = htonl (DAQ__GO);
|
|
|
|
status = send (cnct_skt, (char *) &Req_buff, sizeof (Req_buff), 0);
|
|
if (status == -1) FailInet ("\nSINQHM_CTRL -- send error");
|
|
if (status != sizeof (Req_buff)) {
|
|
printf ("SINQHM_CTRL -- wrong number of bytes sent: %d", status);
|
|
return EXIT_FAILURE;
|
|
}
|
|
/*
|
|
** Wait for the status response.
|
|
*/
|
|
status = getCheckStatusResponse (cnct_skt, &Rply_buff, sizeof (Rply_buff));
|
|
if (status == SUCCESS) {
|
|
daq_state_now = ntohl (Rply_buff.u.daq.daq_now);
|
|
daq_state_was = ntohl (Rply_buff.u.daq.daq_was);
|
|
filler_mask = ntohl (Rply_buff.u.daq.filler_mask);
|
|
if (daq_state_now == 0) {
|
|
if (daq_state_was == 0) {
|
|
printf (" done. It was already active!\n");
|
|
}else {
|
|
printf (" done.\n");
|
|
}
|
|
}else {
|
|
printf ("\n\007 Data acquisition is still disabled.\n"
|
|
" Dsbl_Mask is 0x%08x\n"
|
|
" Filler_Mask is 0x%08x\n", daq_state_now, filler_mask);
|
|
}
|
|
}
|
|
/*
|
|
** Close the connection.
|
|
*/
|
|
status = close (cnct_skt);
|
|
if ((status != 0) && (errno != ECONNRESET))
|
|
FailInet ("\nSINQHM_CTRL -- close error");
|
|
return EXIT_SUCCESS;
|
|
/*============================================================================*/
|
|
rundown:
|
|
/*======= Rundown. Set up and send the rundown message.
|
|
*/
|
|
printf (" Sending SQHM_EXIT command to SinqHM ...");
|
|
Req_buff.bigend = htonl (0x12345678);
|
|
Req_buff.cmnd = htonl (SQHM_EXIT);
|
|
|
|
status = send (cnct_skt, (char *) &Req_buff, sizeof (Req_buff), 0);
|
|
if (status == -1) FailInet ("\nSINQHM_CTRL -- send error");
|
|
if (status != sizeof (Req_buff)) {
|
|
printf ("SINQHM_CTRL -- wrong number of bytes sent: %d", status);
|
|
return EXIT_FAILURE;
|
|
}
|
|
/*
|
|
** Wait for the status response.
|
|
*/
|
|
status = getCheckStatusResponse (cnct_skt, &Rply_buff, sizeof (Rply_buff));
|
|
if (status == SUCCESS) {
|
|
printf (" done.\n");
|
|
}
|
|
/*
|
|
** Close the connection.
|
|
*/
|
|
status = close (cnct_skt);
|
|
if ((status != 0) && (errno != ECONNRESET))
|
|
FailInet ("\nSINQHM_CTRL -- close error");
|
|
return EXIT_SUCCESS;
|
|
/*============================================================================*/
|
|
show:
|
|
/*==== Show-status. Set up and send the status message.
|
|
*/
|
|
printf (" Getting status of SinqHM ...");
|
|
|
|
Req_buff.bigend = htonl (0x12345678);
|
|
Req_buff.cmnd = htonl (SQHM_STATUS);
|
|
|
|
status = send (cnct_skt, (char *) &Req_buff, sizeof (Req_buff), 0);
|
|
if (status == -1) FailInet ("\nSINQHM_CTRL -- send error");
|
|
if (status != sizeof (Req_buff)) {
|
|
printf ("SINQHM_CTRL -- wrong number of bytes sent: %d", status);
|
|
return EXIT_FAILURE;
|
|
}
|
|
/*
|
|
** Wait for the status response.
|
|
*/
|
|
status = getCheckStatusResponse (cnct_skt, &Rply_buff, sizeof (Rply_buff));
|
|
if (status == SUCCESS) {
|
|
/*
|
|
** Display the status obtained.
|
|
*/
|
|
memcpy (buff, (char *) &Rply_buff.sub_status, 4); /* Get SinqHM Ident */
|
|
buff[4] = '\0';
|
|
if (Rply_buff.u.status.cfg_state == 0) {
|
|
printf ("\n SINQHM has not yet been configured.\n");
|
|
printf (" SinqHM Identifier is \"%s\"\n", buff);
|
|
printf (" Maximum number of histograms = %d\n",
|
|
ntohl (Rply_buff.u.status.max_n_hists));
|
|
printf (" Maximum number of bins per histogram = %d\n",
|
|
ntohl (Rply_buff.u.status.max_num_bins));
|
|
printf (" Maximum number of active connections supported = %d\n",
|
|
Rply_buff.u.status.max_srvrs);
|
|
printf (" Maximum space available for histograms = %d bytes\n",
|
|
ntohl (Rply_buff.u.status.max_block));
|
|
}else {
|
|
printf ("\n SinqHM Identifier is \"%s\"\n", buff);
|
|
printf (" Histogramming Mode = 0x%x\n",
|
|
ntohl (Rply_buff.u.status.cfg_state));
|
|
printf (" Number of histograms/Current histogram = %d/%d\n",
|
|
ntohs (Rply_buff.u.status.n_hists),
|
|
ntohs (Rply_buff.u.status.curr_hist));
|
|
printf (" Number of bins per histogram = %d\n",
|
|
ntohl (Rply_buff.u.status.num_bins));
|
|
printf (" Number of bytes per bin = %d\n", Rply_buff.u.status.binwid);
|
|
printf (" Maximum number of active connections supported = %d\n",
|
|
Rply_buff.u.status.max_srvrs);
|
|
printf (" Current number of active connections = %d\n",
|
|
Rply_buff.u.status.act_srvrs);
|
|
printf (" Maximum block of free memory = %d bytes\n",
|
|
ntohl (Rply_buff.u.status.max_block));
|
|
if (Rply_buff.u.status.daq_now == 0) {
|
|
printf (" Data acquisition is active\n");
|
|
}else {
|
|
printf (" Data acquisition is not active\n");
|
|
}
|
|
}
|
|
}
|
|
/*
|
|
** Close the connection.
|
|
*/
|
|
status = close (cnct_skt);
|
|
if ((status != 0) && (errno != ECONNRESET))
|
|
FailInet ("\nSINQHM_CTRL -- close error");
|
|
return EXIT_SUCCESS;
|
|
/*============================================================================*/
|
|
stop:
|
|
/*==== Stop. Get SinqHM-filler to stop taking data.
|
|
*/
|
|
printf (" Stopping data acquisition ...");
|
|
|
|
Req_buff.bigend = htonl (0x12345678);
|
|
Req_buff.cmnd = htonl (SQHM_DAQ);
|
|
Req_buff.u.daq.sub_cmnd = htonl (DAQ__STOP);
|
|
|
|
status = send (cnct_skt, (char *) &Req_buff, sizeof (Req_buff), 0);
|
|
if (status == -1) FailInet ("\nSINQHM_CTRL -- send error");
|
|
if (status != sizeof (Req_buff)) {
|
|
printf ("SINQHM_CTRL -- wrong number of bytes sent: %d", status);
|
|
return EXIT_FAILURE;
|
|
}
|
|
/*
|
|
** Wait for the status response.
|
|
*/
|
|
status = getCheckStatusResponse (cnct_skt, &Rply_buff, sizeof (Rply_buff));
|
|
if (status == SUCCESS) {
|
|
daq_state_now = ntohl (Rply_buff.u.daq.daq_now);
|
|
daq_state_was = ntohl (Rply_buff.u.daq.daq_was);
|
|
filler_mask = ntohl (Rply_buff.u.daq.filler_mask);
|
|
if (daq_state_now != 0) {
|
|
if (daq_state_was == 0) {
|
|
printf (" done.\n");
|
|
}else {
|
|
printf (" done. It was already stopped!\n");
|
|
}
|
|
}else {
|
|
printf ("\n\007 Data acquisition is still enabled!\n"
|
|
" Dsbl_Mask is 0x%08x\n"
|
|
" Filler_Mask is 0x%08x\n", daq_state_now, filler_mask);
|
|
}
|
|
}
|
|
/*
|
|
** Close the connection.
|
|
*/
|
|
status = close (cnct_skt);
|
|
if ((status != 0) && (errno != ECONNRESET))
|
|
FailInet ("\nSINQHM_CTRL -- close error");
|
|
return EXIT_SUCCESS;
|
|
/*============================================================================*/
|
|
zero:
|
|
/*==== Zero. Zero the complete histogram buffer
|
|
*/
|
|
Req_buff.bigend = htonl (0x12345678);
|
|
Req_buff.cmnd = htonl (SQHM_ZERO);
|
|
Req_buff.u.zero.hist_no = htonl (-1);
|
|
Req_buff.u.zero.first_bin = htonl (-1);
|
|
Req_buff.u.zero.n_bins = htonl (-1);
|
|
printf (" Zeroing the histogram memory buffer ...");
|
|
|
|
status = send (cnct_skt, (char *) &Req_buff, sizeof (Req_buff), 0);
|
|
if (status == -1) FailInet ("\nSINQHM_CTRL -- send error");
|
|
if (status != sizeof (Req_buff)) {
|
|
printf ("\nSINQHM_CTRL -- wrong number of bytes sent: %d", status);
|
|
return EXIT_FAILURE;
|
|
}
|
|
/*
|
|
** Wait for the status response.
|
|
*/
|
|
status = getCheckStatusResponse (cnct_skt, &Rply_buff, sizeof (Rply_buff));
|
|
if (status == SUCCESS) {
|
|
printf (" done.\n");
|
|
}
|
|
/*
|
|
** Close the connection.
|
|
*/
|
|
status = close (cnct_skt);
|
|
if ((status != 0) && (errno != ECONNRESET))
|
|
FailInet ("\nSINQHM_CTRL -- close error");
|
|
return EXIT_SUCCESS;
|
|
/*============================================================================*/
|
|
help:
|
|
/*==== Help - give some help.
|
|
*/
|
|
show_help (modifier);
|
|
return EXIT_SUCCESS;
|
|
}
|
|
/*================================================ End of SINQHM_CTRL.C =====*/
|