
- Refactored site specific stuff into a site module - PSI specific stuff is now in the PSI directory. - The old version has been tagged with pre-ansto
2706 lines
94 KiB
C
Executable File
2706 lines
94 KiB
C
Executable File
#define IDENT "1A03"
|
||
/*
|
||
** +--------------------------------------------------------------+
|
||
** | Paul Scherrer Institute |
|
||
** | SINQ Division |
|
||
** | |
|
||
** | 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 . . . . . . . . : [...SinqHM]FOCUS_srv_main.c
|
||
**
|
||
** Author . . . . . . . . . . : D. Maden
|
||
** Date of creation . . . . . . : Mar 2000
|
||
** Well, start a motor. But not a3 in powder mode in order to
|
||
|
||
** Updates:
|
||
** 1A01 7-Mar-2000 DM Initial version.
|
||
**---------------------------------------------------------------------------
|
||
** FOCUS_srv_main.c is the main program of a SINQ Histogram Memory process
|
||
** for the FOCUS TOF spectrometer at SINQ. It acts as an intermediary between
|
||
** host software, which believes that it is talking to a single version of
|
||
** SinqHM_srv, and 3 copies of SinqHM_srv on 3 different front-end processors,
|
||
** each of which is histogramming data from one of the 3 detector banks on
|
||
** FOCUS.
|
||
**
|
||
** Communication between FOCUS_srv and the client is via TCP/IP protocol.
|
||
**
|
||
** To compile and link this program for VxWorks on PSS123, use:
|
||
**
|
||
ccvx '-DINST="<instr>"' FOCUS_srv_main.c
|
||
ccvx '-DINST="<instr>"' FOCUS_srv_server.c
|
||
ccvx '-DINST="<instr>"' FOCUS_srv_routines.c
|
||
** where
|
||
ccvx = ccppc -O0 \
|
||
-mcpu=603 \
|
||
-I${WIND_BASE}/target/h \
|
||
-fno-builtin \
|
||
-fno-for-scope \
|
||
-nostdinc \
|
||
-DCPU=PPC603 \
|
||
-D_GNU_TOOL \
|
||
-gdwarf -c -Wimplicit
|
||
** and
|
||
** <instr> = FOCUS or ...
|
||
|
||
ldppc -o FOCUS_srv.o -r FOCUS_srv_main.o \
|
||
FOCUS_srv_routines.o \
|
||
FOCUS_srv_server.o
|
||
|
||
** and, on the target,
|
||
**
|
||
** -> ld < /home/pss123/aco/maden/wind/SinqHM/FOCUS/NEW/FOCUS_srv.o
|
||
** -> sp FOCUS_main, \
|
||
** <hostM>, <ncM>, <hostO>, <ncO>, <hostU>, <ncU>, <c_port>, <s_port>
|
||
** ^ ^ ^ ^ ^ ^ ^ ^
|
||
** Name of Host | | | | | | | |
|
||
** for Mittel-Bnk+ | | | | | | |
|
||
** # Counters in Mittel- + | | | | | |
|
||
** Bank | | | | | |
|
||
** Name of Host for Ober-Bank ---+ | | | | |
|
||
** # Counters in Ober-Bank --------------+ | | | |
|
||
** Name of Host for Unter-Bank ------------------+ | | |
|
||
** # Counters in Unter-Bank -----------------------------+ | |
|
||
** Port number of Bank Servers (dflt = 2500) --------------------+ |
|
||
** Our Port number as a Server (dflt = 2400) ------------------------------+
|
||
** e.g.
|
||
** sp FOCUS_main, "localhost", 150, "lnse05.vme", 117, "lnse06.vme", 116
|
||
** or sps FOCUS_main, "localhost", 150, "lnse05.vme", 117, "lnse06.vme", 116
|
||
**====================================================================
|
||
*/
|
||
#include "vxWorks.h"
|
||
#include "taskLib.h"
|
||
#include "msgQLib.h"
|
||
#include "sockLib.h"
|
||
#include "inetLib.h"
|
||
#include "sysLib.h"
|
||
|
||
#include <stdlib.h>
|
||
#include <stdio.h>
|
||
#include <ctype.h>
|
||
#include <string.h>
|
||
#include <unistd.h>
|
||
#include <errno.h>
|
||
#include <netinet/in.h>
|
||
#include <arpa/inet.h>
|
||
#include <netdb.h>
|
||
#include <sys/types.h>
|
||
#include <sys/socket.h>
|
||
#include <setjmp.h>
|
||
#include <time.h>
|
||
|
||
#include <signal.h> /* Get POSIX signal definitions. */
|
||
#include <timers.h>
|
||
#include <sys/mman.h> /* Get POSIX mem mgmnt definitions. */
|
||
#include <sys/wait.h> /* Get POSIX wait definitions. */
|
||
/*
|
||
**==================== Global Definitions =====================================
|
||
*/
|
||
#include "SinqHM_def.h"
|
||
#include "FOCUS_gbl.h"
|
||
|
||
#define READBUFSIZE 66560
|
||
extern char *vxWorksVersion; /* Version string of vxWorks */
|
||
extern char *creationDate; /* Creation Date string of vxWorks */
|
||
static uchar readBuffer[READBUFSIZE];
|
||
|
||
/*
|
||
**=============================================================================
|
||
** Local routines.
|
||
**--------------------------------------------------------------------------
|
||
** FOCUS_server: This is the Child Process Code for FOCUS_srv.
|
||
**
|
||
** Set up TCP/IP port for operations with client, accept his
|
||
** connection and perform services for him.
|
||
**
|
||
** Note: There must be NO return from this function.
|
||
*/
|
||
int FOCUS_server (
|
||
/* ============
|
||
*/ pid_t parent_pid,
|
||
SEM_ID sem,
|
||
int index,
|
||
int pkt_size,
|
||
int suspend_flag,
|
||
int *iret) { /* Return a status to parent here:
|
||
** 0 = all OK
|
||
** -1 = sigaction error.
|
||
** -2 = socket or bind error with cnct_skt.
|
||
** -3 = listen error with cnct_skt.
|
||
** -4 = socket or bind error with clnt_skt.
|
||
** -5 = failed to connect to a slave mstr.
|
||
** -6 = SQHM_CNCT error response from slave.
|
||
** -7 = socket or bind error with child.
|
||
** -8 = failed to connect to a slave srvr.
|
||
*/
|
||
int status;
|
||
int i, is, nbytes, bytes_to_come;
|
||
char recd[80];
|
||
char *p_nxt_byte;
|
||
int cnct_skt, rw_skt, clnt_skt, serve_port;
|
||
struct sockaddr_in rmt_sockname;
|
||
int rmt_sockname_len;
|
||
char *buff_pntr;
|
||
int port;
|
||
|
||
sigset_t proc_sigmask;
|
||
struct sigaction sig_action;
|
||
|
||
struct req_buff_struct my_req_bf;
|
||
struct rply_buff_struct my_rply_bf;
|
||
|
||
/*============================================================================
|
||
*/
|
||
*iret = 0; /* Assume initialisation will be OK */
|
||
|
||
port = FS_port + index;
|
||
|
||
StrJoin (FS_name[index], sizeof (FS_name[0]), taskName (get_pid ()), "");
|
||
|
||
if (suspend_flag != 0) {
|
||
printf ("\n%s: Suspending ..\n", FS_name[index]);
|
||
taskSuspend (0); /* We've been told to suspend ourself, ..
|
||
** .. presumably for debug reasons.
|
||
*/
|
||
printf ("\n%s: Suspension ended!\n", FS_name[index]);
|
||
}
|
||
/*============================================================================
|
||
** Define our signal mask first and define an action routine to catch
|
||
** the SIGINT signal our parent will send us when he wants us to exit.
|
||
*/
|
||
status = sigemptyset (&proc_sigmask);
|
||
status = sigprocmask (SIG_SETMASK, &proc_sigmask, NULL);
|
||
|
||
status = sigemptyset (&sig_action.sa_mask);
|
||
sig_action.sa_handler = FS_catch_int_signal;
|
||
sig_action.sa_flags = 0;
|
||
if (sigaction (SIGINT, &sig_action, NULL) == -1) {
|
||
getErrno (&FS_errno);
|
||
perror ("sigaction error:");
|
||
*iret = -1; /* Tell our parent we've given up */
|
||
is = semGive (sem); /* Let our parent continue */
|
||
exit (KER__BAD_VALUE);
|
||
}
|
||
/*============================================================================
|
||
** Create a TCP/IP socket for communication, bind it and listen.
|
||
*/
|
||
FS_chld_cnct_skt[index] = 0;
|
||
cnct_skt = socket_bind (port, FS_name[index]);
|
||
if (cnct_skt == -1) {
|
||
*iret = -2; /* Tell our parent we've given up */
|
||
is = semGive (sem); /* Let our parent continue */
|
||
exit (KER__BAD_VALUE);
|
||
}
|
||
|
||
status = listen (cnct_skt, 1);
|
||
if (status != 0) {
|
||
close (cnct_skt);
|
||
perror (StrJoin (recd, sizeof (recd),
|
||
FS_name[index], " -- cnct_skt listen error"));
|
||
*iret = -3; /* Tell our parent we've given up */
|
||
is = semGive (sem); /* Let our parent continue */
|
||
exit (KER__BAD_VALUE);
|
||
}
|
||
/*============================================================================
|
||
** Now open client connections to each of the Slaves
|
||
*/
|
||
my_req_bf.bigend = htonl (0x12345678);
|
||
my_req_bf.cmnd = htonl (SQHM_CNCT);
|
||
my_req_bf.u.cnct.max_pkt = htonl (pkt_size);
|
||
my_req_bf.u.cnct.strt_mode = 0;
|
||
for (i = 0; i < FS_n_slaves; i++) {
|
||
if (FS_slv_active[i]) {
|
||
/*
|
||
** Create a socket and bind it
|
||
*/
|
||
clnt_skt = socket_bind (0, FS_name[index]);
|
||
if (clnt_skt == -1) {
|
||
*iret = -4; /* Tell our parent we've given up */
|
||
FS_close_all (index); /* Shut down any client cnct'ns we've made */
|
||
close (cnct_skt);
|
||
is = semGive (sem); /* Let our parent continue */
|
||
exit (KER__BAD_VALUE);
|
||
}
|
||
/*
|
||
** Make a connection to Master-server in slave
|
||
*/
|
||
rmt_sockname_len = sizeof (FS_rmt_socknam[0]);
|
||
status = connect (clnt_skt, (struct sockaddr *) &FS_rmt_socknam[i],
|
||
rmt_sockname_len);
|
||
if (status == -1) {
|
||
StrJoin (recd, sizeof (recd),
|
||
": error connecting to master in ", FS_slaves[i]);
|
||
perror (StrJoin (recd, sizeof (recd), FS_name[index], recd));
|
||
*iret = -5; /* Tell our parent we've given up */
|
||
close (clnt_skt);
|
||
FS_close_all (index); /* Shut down any client cnct'ns we've made */
|
||
close (cnct_skt);
|
||
is = semGive (sem); /* Let our parent continue */
|
||
exit (KER__BAD_VALUE);
|
||
}
|
||
/*
|
||
** Send SQHM_CNCT command to Master-server and get response
|
||
*/
|
||
status = rqst_send_get (clnt_skt, &my_req_bf, sizeof (my_req_bf),
|
||
&my_rply_bf, sizeof (my_rply_bf),
|
||
&FS_bytes_got, &FS_bytes_put, FS_name[index]);
|
||
if (!status || (ntohl (my_rply_bf.status) != KER__SUCCESS)) {
|
||
if (ntohl (my_rply_bf.status) != KER__SUCCESS) {
|
||
printf (
|
||
"\n%s: %s to %s.\n, status = %d, substatus = %d ",
|
||
"error response to SINQHM_CNCT",
|
||
FS_name[index], FS_slaves[i],
|
||
ntohl(my_rply_bf.status),
|
||
ntohl(my_rply_bf.sub_status));
|
||
}
|
||
*iret = -6; /* Tell our parent we've given up */
|
||
close (clnt_skt);
|
||
FS_close_all (index); /* Shut down any client cnct'ns we've made */
|
||
close (cnct_skt);
|
||
is = semGive (sem); /* Let our parent continue */
|
||
exit (KER__BAD_VALUE);
|
||
}
|
||
close (clnt_skt);
|
||
serve_port = ntohl (my_rply_bf.u.cnct.port);
|
||
FS_pkt_siz[index][i] = ntohl (my_rply_bf.u.cnct.pkt_size);
|
||
/*
|
||
** Create a socket for talking to our server in slave and bind
|
||
*/
|
||
clnt_skt = socket_bind (0, FS_name[index]);
|
||
if (clnt_skt == -1) {
|
||
*iret = -7; /* Tell our parent we've given up */
|
||
FS_close_all (index); /* Shut down any client cnct'ns we've made */
|
||
close (cnct_skt);
|
||
is = semGive (sem); /* Let our parent continue */
|
||
exit (KER__BAD_VALUE);
|
||
}
|
||
/*
|
||
** Make a connection to our server in slave
|
||
*/
|
||
rmt_sockname = FS_rmt_socknam[i];
|
||
rmt_sockname.sin_port = htons (serve_port);
|
||
rmt_sockname_len = sizeof (rmt_sockname);
|
||
status = connect (clnt_skt, (struct sockaddr *) &rmt_sockname,
|
||
rmt_sockname_len);
|
||
if (status == -1) {
|
||
StrJoin (recd, sizeof (recd),
|
||
": error connecting to server in ", FS_slaves[i]);
|
||
perror (StrJoin (recd, sizeof (recd), FS_name[index], recd));
|
||
*iret = -8; /* Tell our parent we've given up */
|
||
close (clnt_skt);
|
||
FS_close_all (index); /* Shut down any client cnct'ns we've made */
|
||
close (cnct_skt);
|
||
is = semGive (sem); /* Let our parent continue */
|
||
exit (KER__BAD_VALUE);
|
||
}
|
||
FS_skt[index][i] = clnt_skt;
|
||
}
|
||
}
|
||
/*============================================================================
|
||
** Tell parent our cnct port is set up and waiting by releasing
|
||
** semaphore so that our parent can continue. The parent will then
|
||
** send a message to the client telling him which port he is to use.
|
||
*/
|
||
FS_chld_cnct_skt[index] = cnct_skt;
|
||
is = semGive (sem);
|
||
if (is != OK) {
|
||
kill (parent_pid, SIGUSR1); /* Inform parent that we are in trouble */
|
||
printf ("\n%s -- sem release error\n", FS_name[index]);
|
||
close (FS_chld_cnct_skt[index]); FS_chld_cnct_skt[index] = 0;
|
||
FS_close_all (index); /* Close connections to our servers */
|
||
exit (KER__BAD_VALUE);
|
||
}
|
||
/*============================================================================
|
||
** Wait for the client to connect to our port
|
||
*/
|
||
rmt_sockname_len = sizeof (rmt_sockname);
|
||
rw_skt = accept (FS_chld_cnct_skt[index],
|
||
(struct sockaddr *) &rmt_sockname, &rmt_sockname_len);
|
||
if (rw_skt == -1) {
|
||
perror (StrJoin (recd, sizeof (recd),
|
||
FS_name[index], " -- cnct_skt accept error"));
|
||
close (FS_chld_cnct_skt[index]); FS_chld_cnct_skt[index] = 0;
|
||
FS_close_all (index); /* Close connections to our servers */
|
||
kill (parent_pid, SIGUSR1); /* Inform parent that we are in trouble */
|
||
exit (KER__BAD_VALUE);
|
||
}
|
||
FS_chld_rw_skt[index] = rw_skt;
|
||
/*
|
||
**-------------------------------------------------------------------------
|
||
** Here is the main recv loop
|
||
*/
|
||
main_loop:
|
||
/*=========
|
||
*/ bytes_to_come = sizeof (my_req_bf); /* Read a command */
|
||
p_nxt_byte = (char *) &my_req_bf;
|
||
while (bytes_to_come > 0) {
|
||
nbytes = recv (FS_chld_rw_skt[index], p_nxt_byte, bytes_to_come, 0);
|
||
if (nbytes <= 0) break;
|
||
FS_bytes_got += nbytes;
|
||
bytes_to_come -= nbytes;
|
||
p_nxt_byte += nbytes;
|
||
}
|
||
if ((bytes_to_come == 0) &&
|
||
(ntohl (my_req_bf.bigend) == 0x12345678) &&
|
||
(ntohl (my_req_bf.cmnd) != SQHM_CLOSE)) {
|
||
is = FS_do_command (index, FS_chld_rw_skt[index], pkt_size,
|
||
&my_req_bf, &my_rply_bf);
|
||
if (is) goto main_loop; /* Break out of loop on error */
|
||
}
|
||
/*
|
||
** End of the main recv loop
|
||
**-------------------------------------------------------------------------
|
||
** Get here if we drop out of the "recv" loop.
|
||
** This should only happen on getting a SQHM_CLOSE message or if our
|
||
** client closes his socket without sending a SQHM_CLOSE message.
|
||
** Anything else is a fatal error.
|
||
*/
|
||
close (FS_chld_rw_skt[index]); FS_chld_rw_skt[index] = 0;
|
||
close (FS_chld_cnct_skt[index]); FS_chld_cnct_skt[index] = 0;
|
||
/*
|
||
** Check the various error conditions
|
||
*/
|
||
if (bytes_to_come != 0) { /* Was a complete request read? */
|
||
/* No, it may be a network error, in which case
|
||
** nbytes is -1, or nothing was read, which
|
||
** indicates that our client simply closed
|
||
** his connection (forgetting to send a
|
||
** SQHM_CLOSE message), or the client has
|
||
** screwed up the protocol! */
|
||
if (nbytes == -1) {
|
||
/* It's a network error */
|
||
perror (StrJoin (recd, sizeof (recd),
|
||
FS_name[index], " -- rw_skt recv error"));
|
||
status = KER__EXIT_SIGNAL;
|
||
}else if (bytes_to_come == sizeof (my_req_bf)) {
|
||
/* Our client simply closed his connection.
|
||
** Treat this as normal. */
|
||
printf ("\n%s exiting.\n", FS_name[index]);
|
||
status = KER__SUCCESS;
|
||
}else {
|
||
printf ("\n%s -- rw_skt recv wrong number of bytes: %d\n",
|
||
FS_name[index], nbytes);
|
||
status = KER__EXIT_SIGNAL;
|
||
}
|
||
}else if (ntohl (my_req_bf.bigend) != 0x12345678) {
|
||
/* Network byte-order wrong! */
|
||
printf ("\n%s -- big-endian/little-endian problem!\n"
|
||
" Buffer received in non-network byte order!\n", FS_name[index]);
|
||
status = KER__EXIT_SIGNAL;
|
||
}else if (ntohl (my_req_bf.cmnd) == SQHM_CLOSE) {
|
||
/* SQHM_CLOSE request received. This is normal */
|
||
printf ("\n%s exiting.\n", FS_name[index]);
|
||
status = KER__SUCCESS;
|
||
}else {
|
||
/* Unrecognised request received! */
|
||
printf ("\n%s -- unrecognised command received: 0x%x\n",
|
||
FS_name[index], ntohl (my_req_bf.cmnd));
|
||
status = KER__EXIT_SIGNAL;
|
||
}
|
||
|
||
FS_close_all (index); /* Close connections to our servers */
|
||
kill (parent_pid, SIGUSR1); /* Inform parent that we are exiting */
|
||
exit (status);
|
||
}
|
||
/*
|
||
**--------------------------------------------------------------------------
|
||
*/
|
||
void FS_catch_signal (int signo) {
|
||
/* ===============
|
||
** Action Routine for catching signals from Child Processes.
|
||
**
|
||
** This routine is specific to FOCUS_srv.
|
||
*/
|
||
pid_t my_pid;
|
||
|
||
my_pid = get_pid ();
|
||
if (FS_dbg_lev0) printf ("\nFS_catch_signal: "
|
||
"Signal %d received by PID 0x%x.\n", signo, my_pid);
|
||
switch (signo) {
|
||
case SIGUSR1: /* A child is about to exit. */
|
||
FS_cnt_SIGUSR1++;
|
||
sleep (1); /* Give it a chance to disappear! */
|
||
break;
|
||
default:
|
||
printf ("\nFS_catch_signal: Unexpected signal received "
|
||
"by PID 0x%x: %d.\n", my_pid, signo);
|
||
}
|
||
}
|
||
/*
|
||
**--------------------------------------------------------------------------*/
|
||
void FS_catch_int_signal (int signo) {
|
||
/* ===================
|
||
** Action Routine for catching SIGINT signals. This is a signal
|
||
** from the parent to get its child to exit. An exit will be performed.
|
||
**
|
||
** This routine is specific to FOCUS_srv.
|
||
*/
|
||
int i, j;
|
||
pid_t my_pid;
|
||
|
||
my_pid = get_pid ();
|
||
/*
|
||
** Try to find our index by searching the PID list
|
||
*/
|
||
if (my_pid == FS_pids[0]) {
|
||
; /* Should not get here - there's no Filler
|
||
** for FOCUS_srv! */
|
||
}else {
|
||
for (i = MAX_CLIENTS; i > 0; i--) if (my_pid == FS_pids[i]) break;
|
||
if (i > 0) {
|
||
if (FS_chld_rw_skt[i] != 0) {
|
||
printf ("\nClosing r/w socket of task %s\n", FS_name[i]);
|
||
close (FS_chld_rw_skt[i]); FS_chld_rw_skt[i] = 0;
|
||
}
|
||
if (FS_chld_cnct_skt[i] != 0) {
|
||
printf ("\nClosing connect socket of task %s\n", FS_name[i]);
|
||
close (FS_chld_cnct_skt[i]); FS_chld_cnct_skt[i] = 0;
|
||
}
|
||
for (j = 0; j < FS_n_slaves; j++) {
|
||
if (FS_skt[i][j] != 0) {
|
||
printf ("\nClosing client socket of task %s to %s\n",
|
||
FS_name[i], FS_slaves[i]);
|
||
close (FS_skt[i][j]); FS_skt[i][j] = 0;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
if (FS_dbg_lev0) printf ("\nFS_catch_int_signal: "
|
||
"Signal %d received by PID 0x%x.\n", signo, my_pid);
|
||
switch (signo) {
|
||
case SIGINT: /* A SIGINT signal has been received. Exit. */
|
||
exit (KER__SUCCESS);
|
||
break;
|
||
default:
|
||
printf ("\nFS_catch_int_signal: "
|
||
"Unexpected signal %d received by PID 0x%x.\n", signo, my_pid);
|
||
}
|
||
}
|
||
/*
|
||
**--------------------------------------------------------------------------
|
||
** FS_cleanup_children: Find out which child(ren) have exited and
|
||
** update the list of task PID's so the associated
|
||
** task slot becomes free.
|
||
**
|
||
** If FILLER should be present but has fallen off, then any
|
||
** active children will be told to exit and we shall set our
|
||
** state to "deconfig".
|
||
*/
|
||
void FS_cleanup_children (
|
||
/* ===================
|
||
*/ int max_chld, /* The size of the pids array */
|
||
pid_t *pids, /* Array of pids. Index 0 is FILLER */
|
||
int *pcnt_SIGUSR1, /* Flag set on SIGUSR1 signals whenever
|
||
** a child exits. */
|
||
int verbose, /* If true, report what's going on */
|
||
char **tsk_names,
|
||
char *filler_name) {
|
||
|
||
int i, status, n_active, do_newline = False;
|
||
char *t_name;
|
||
pid_t pid;
|
||
|
||
if (pids[0] != 0) {
|
||
if (verbose) printf ("\n ... checking state of %s ...", filler_name);
|
||
t_name = taskName (pids[0]);
|
||
if (t_name == NULL) {
|
||
if (verbose) printf (" it has exited.");
|
||
pids[0] = 0;
|
||
}else {
|
||
if (verbose) printf (" it is still active.");
|
||
}
|
||
if (verbose) do_newline = True;
|
||
}
|
||
|
||
n_active = 0;
|
||
for (i = 1; i <= max_chld; i++) {
|
||
if (pids[i] != 0) {
|
||
if (verbose) printf ("\n ... checking state of %s ...", tsk_names[i]);
|
||
t_name = taskName (pids[i]);
|
||
if (t_name == NULL) {
|
||
if (verbose) printf (" it has exited.");
|
||
pids[i] = 0;
|
||
}else {
|
||
if (verbose) printf (" it is still active.");
|
||
n_active += 1;
|
||
}
|
||
if (verbose) do_newline = True;
|
||
}
|
||
}
|
||
if (do_newline) printf ("\n");
|
||
if (pcnt_SIGUSR1 != NULL) *pcnt_SIGUSR1 = 0;
|
||
|
||
if ((filler_name[0] != NIL) && /* Must we force a de-config? */
|
||
(pids[0] == 0) &&
|
||
(n_active > 0)) {
|
||
for (;;) { /* Loop for ever till programmed! */
|
||
printf ("\nThe filler process, %s, has terminated abnormally.\n"
|
||
"A de-configure must be forced\n"
|
||
"This has not yet been programmed.\n"
|
||
"Re-boot the histogram memory!!\n", filler_name);
|
||
sleep (5);
|
||
}
|
||
}
|
||
}
|
||
/*
|
||
**--------------------------------------------------------------------------
|
||
** FS_close_all: Shut down any active client cnct'ns
|
||
*/
|
||
int FS_close_all (
|
||
/* ============
|
||
*/ int index) {
|
||
|
||
int i, status;
|
||
char recd[80];
|
||
struct req_buff_struct my_req_bf;
|
||
struct rply_buff_struct my_rply_bf;
|
||
|
||
my_req_bf.bigend = htonl (0x12345678);
|
||
my_req_bf.cmnd = htonl (SQHM_CLOSE);
|
||
for (i = 0; i < FS_n_slaves; i++) {
|
||
if (FS_skt[index][i] != 0) {
|
||
status = send (FS_skt[index][i],
|
||
(char *) &my_req_bf, sizeof (my_req_bf), 0);
|
||
if (status == -1) {
|
||
perror (StrJoin (recd, sizeof (recd),
|
||
FS_name[index], "/rqst_send_get: send error"));
|
||
}
|
||
close (FS_skt[index][i]);
|
||
FS_skt[index][i] = 0;
|
||
}
|
||
}
|
||
}
|
||
/*
|
||
**--------------------------------------------------------------------------
|
||
** FS_close_down_offspring: Close down FILLER and, if directed,
|
||
** other children too.
|
||
*/
|
||
int FS_close_down_offspring (
|
||
/* =======================
|
||
*/ int harshness,
|
||
int max_chld,
|
||
pid_t *pids,
|
||
int *exit_stat,
|
||
int *pcnt_SIGUSR1, /* Flag set on SIGUSR1 signals
|
||
** whenever a child exits. */
|
||
int verbose, /* If true, report what's going on */
|
||
char **tsk_names,
|
||
char *filler_name) {
|
||
|
||
int i, j;
|
||
int n_children, new_c = 0;
|
||
char buff[132];
|
||
|
||
n_children = 0; /* See if any server children are active */
|
||
for (i = 1; i <= max_chld; i++) {
|
||
if (pids[i] != 0) n_children += 1;
|
||
}
|
||
if (n_children > 0) { /* If so, only proceed if asked to be ruthless */
|
||
if (harshness == 0) {
|
||
printf ("\nDe-configure error. ");
|
||
if (n_children == 1) sprintf (buff, "1 server is");
|
||
if (n_children != 1) sprintf (buff, "%d servers are", n_children);
|
||
printf ("%s still active.\n", buff);
|
||
return False;
|
||
}else {
|
||
if (n_children == 1) sprintf (buff, " -- 1 server is still active. It");
|
||
if (n_children != 1) sprintf (buff, " -- %d servers are still active. "
|
||
"They", n_children);
|
||
printf ("\n%s will be terminated.\n", buff);
|
||
}
|
||
}
|
||
|
||
FS_kill_children (max_chld, pids,
|
||
tsk_names, filler_name); /* Kill FILLER and any server children */
|
||
sleep (1); /* Give them chance to exit */
|
||
FS_cleanup_children (max_chld, pids, /* Update the PIDs */
|
||
pcnt_SIGUSR1, verbose, tsk_names, filler_name);
|
||
|
||
for (j = 0; j < n_children; j++) { /* Check to see if all gone */
|
||
if (pids[0] == 0) new_c = 0; else new_c = 1; /* Count remainder */
|
||
for (i = max_chld; i > 0; i--) {
|
||
if (pids[i] != 0) new_c += 1;
|
||
}
|
||
if (new_c == 0) break;
|
||
sleep (1);
|
||
FS_cleanup_children (max_chld, pids,
|
||
pcnt_SIGUSR1, verbose, tsk_names, filler_name);
|
||
}
|
||
if (new_c != 0) {
|
||
printf (" ... failed to tidy up. %d children still active.\n", new_c);
|
||
return False;
|
||
}else {
|
||
return True;
|
||
}
|
||
}
|
||
/*
|
||
**--------------------------------------------------------------------------
|
||
** FS_deconfig_all: Deconfigure any active slaves.
|
||
**
|
||
** This routine is specific to FOCUS_srv.
|
||
*/
|
||
int FS_deconfig_all (int harshness) {
|
||
/* ===============
|
||
*/
|
||
int i, iret, all_ok = True;
|
||
struct req_buff_struct rqst;
|
||
struct rply_buff_struct reply;
|
||
|
||
rqst.bigend = htonl (0x12345678); /* Set up the deconfig request */
|
||
rqst.cmnd = htonl (SQHM_DECONFIG);
|
||
rqst.u.decnfg.sub_code = htonl (harshness);
|
||
/*
|
||
** Loop sending it to active slaves
|
||
*/
|
||
for (i = 0; i < FS_n_slaves; i++) {
|
||
if (FS_slv_active[i]) {
|
||
iret = FS_send_cmnd_to_mstr (&FS_rmt_socknam[i],
|
||
&rqst, sizeof (rqst), &reply,
|
||
&FS_bytes_got, &FS_bytes_put);
|
||
if (iret && (ntohl (reply.status) == KER__SUCCESS)) {
|
||
FS_slv_active[i] = False;
|
||
}else {
|
||
all_ok = False;
|
||
}
|
||
}
|
||
}
|
||
return all_ok;
|
||
}
|
||
/*
|
||
**--------------------------------------------------------------------------
|
||
** FS_do_command: Action routine for an SQHM_??? command.
|
||
** The command is processed (including returning a
|
||
** status response message).
|
||
**
|
||
** This routine is specific to FOCUS_srv.
|
||
*/
|
||
int FS_do_command (
|
||
/* =============
|
||
*/ int index,
|
||
int skt,
|
||
int pkt_size,
|
||
struct req_buff_struct *rqst,
|
||
struct rply_buff_struct *reply) {
|
||
|
||
int status, indx, is, suspendMode, i, j, sub_cmnd;
|
||
int txt_len, txt_offset, bytes_to_go, harshness;
|
||
int my_first_bin, my_nbins, my_bytes_per_bin, my_hist_no;
|
||
int my_sub_code, my_x_lo, my_nx, my_y_lo, my_ny, my_xdim, my_h_slct;
|
||
time_t secs;
|
||
char *msge, *p_buff, *p_txt;
|
||
|
||
reply->bigend = htonl (0x12345678); /* Put in the "endian" flag. */
|
||
rply_status_setup (reply, KER__SUCCESS, 0, "All OK");
|
||
|
||
switch (ntohl (rqst->cmnd)) {
|
||
|
||
case SQHM_CLOSE: /* Close the connection. */
|
||
return False; /* Do nothing. */
|
||
|
||
case SQHM_CNCT: /* Make a new connection. */
|
||
printf ("\n%s: connecting ...", FS_name[index]);
|
||
|
||
time (&secs);
|
||
secs = secs - FS_start_time;
|
||
reply->u.cnct.up_time = htonl (secs);
|
||
|
||
if (!FS_cfgn_done) { /* Check we've been configured */
|
||
printf (" but not yet configured!\n");
|
||
is = FS_rply_status_setup_and_send (skt, reply, KER__BAD_STATE, 0,
|
||
"Not configured", &FS_bytes_put);
|
||
}else if (index != 0) {
|
||
printf (" but not issued to SinqHM-master!\n");
|
||
is = FS_rply_status_setup_and_send (skt, reply, KER__BAD_STATE, 0,
|
||
"Not SinqHM-master", &FS_bytes_put);
|
||
}else {
|
||
pkt_size = ntohl (rqst->u.cnct.max_pkt);
|
||
if ((pkt_size < 1024) || (pkt_size > 8192)) pkt_size = 8192;
|
||
pkt_size = pkt_size & ~3; /* Ensure pkt_size is multiple of 4 */
|
||
indx = FS_make_child (FOCUS_server, 100,
|
||
ntohl (rqst->u.cnct.strt_mode), pkt_size,
|
||
MAX_CLIENTS, FS_pids, FS_chld_exit_status,
|
||
&FS_cnt_SIGUSR1, "FSserv");
|
||
if (indx <= 0) { /* Child created and ready? */
|
||
printf ("\n%s: creation of child failed: %d.\n",
|
||
FS_name[0], indx);
|
||
switch (indx) {
|
||
case -1: msge = "Spawn failed"; break;
|
||
case -2: msge = "No more ports"; break;
|
||
case -3: msge = "Time-out of child start-up"; break;
|
||
case -4: msge = "Child could not get started"; break;
|
||
default: msge = "Bad status from make_child";
|
||
}
|
||
is = FS_rply_status_setup_and_send (skt, reply, KER__BAD_CREATE,
|
||
indx, msge, &FS_bytes_put);
|
||
}else { /* Yes, child is up and ready. */
|
||
reply->u.cnct.port = htonl (FS_port + indx);
|
||
reply->u.cnct.pkt_size = htonl (pkt_size);
|
||
reply->u.cnct.hm_mode = htonl (FS_mode_ALL);
|
||
reply->u.cnct.n_hists = htonl (FS_hi_cntr - FS_lo_cntr + 1);
|
||
reply->u.cnct.num_bins = htonl (FS_hi_bin - FS_lo_bin + 1);
|
||
reply->u.cnct.bytes_per_bin = htonl (FS_bpb);
|
||
reply->u.cnct.curr_hist = htonl (0);
|
||
reply->u.cnct.max_block = htonl (memFindMax ()); /* Max free mem */
|
||
reply->u.cnct.total_bytes = htonl (FS_totl_bytes);
|
||
reply->u.cnct.lo_cntr = htonl (FS_lo_cntr);
|
||
reply->u.cnct.lo_bin = htonl (FS_lo_bin);
|
||
reply->u.cnct.compress = htonl (FS_compress);
|
||
printf (" %s started. Packet size = %d.\n", FS_name[indx], pkt_size);
|
||
is = FS_rply_status_send (skt, reply, &FS_bytes_put);
|
||
}
|
||
}
|
||
if (!is)
|
||
printf ("\n%s -- send of status reply failed.\n", FS_name[index]);
|
||
return is;
|
||
|
||
case SQHM_CONFIG:
|
||
printf ("\n%s: Configure ..", FS_name[index]);
|
||
if (FS_cfgn_done) {
|
||
is = FS_rply_status_setup_and_send (skt, reply, KER__BAD_STATE, 0,
|
||
"Already configured", &FS_bytes_put);
|
||
printf (" already configured!\n");
|
||
return False;
|
||
}
|
||
|
||
FS_free_memory (NULL); /* There should be no memory allocated but
|
||
** go and release it anyway!
|
||
*/
|
||
is = FS_do_config (skt, rqst, reply); /* No, do the config */
|
||
if (!is) {
|
||
FS_rply_status_send (skt, reply, &FS_bytes_put);
|
||
return False;
|
||
}else {
|
||
FS_cfgn_done = True;
|
||
is = FS_rply_status_send (skt, reply, &FS_bytes_put);
|
||
if (!is)
|
||
printf ("\n%s -- send of status reply failed.\n", FS_name[index]);
|
||
return is;
|
||
}
|
||
|
||
case SQHM_DAQ: /* Start or stop data acquisition.
|
||
** Simply forward to our slaves. */
|
||
printf ("\n%s: SQHM_DAQ", FS_name[index]);
|
||
if (!FS_cfgn_done) { /* Configured yet? */
|
||
FS_rply_status_setup_and_send (skt, reply, KER__BAD_STATE, 0, /* No */
|
||
"Not configured", &FS_bytes_put);
|
||
printf (" -- not configured!\n");
|
||
return False;
|
||
}
|
||
sub_cmnd = ntohl (rqst->u.daq.sub_cmnd);
|
||
if (sub_cmnd == DAQ__CLR) printf ("/DAQ__CLR:");
|
||
if (sub_cmnd == DAQ__GO) printf ("/DAQ__GO:");
|
||
if (sub_cmnd == DAQ__INH) printf ("/DAQ__INH:");
|
||
if (sub_cmnd == DAQ__STOP) printf ("/DAQ__STOP:");
|
||
if (sub_cmnd == DAQ__TST) printf ("/DAQ__TST:");
|
||
|
||
is = FS_do_daq (index, sub_cmnd, rqst, reply);
|
||
|
||
if (FS_dsbl_mask == 0) {
|
||
printf (" data acquisition is active.\n");
|
||
}else {
|
||
printf (" data acquisition is inhibited.\n");
|
||
}
|
||
|
||
is = FS_rply_status_send (skt, reply, &FS_bytes_put);
|
||
if (!is)
|
||
printf ("\n%s -- send of status reply failed.\n", FS_name[index]);
|
||
return is;
|
||
|
||
case SQHM_DBG: /* Set debug parameters.
|
||
** Just do this locally. Do not
|
||
** pass on to slaves. */
|
||
FS_dbg_mask = ntohl (rqst->u.dbg.mask);
|
||
FS_dbg_lev0 = ((FS_dbg_mask & 1) != 0) ? 1 : 0;
|
||
FS_dbg_lev1 = ((FS_dbg_mask & 2) != 0) ? 1 : 0;
|
||
FS_dbg_lev2 = ((FS_dbg_mask & 4) != 0) ? 1 : 0;
|
||
FS_dbg_lev3 = ((FS_dbg_mask & 8) != 0) ? 1 : 0;
|
||
printf ("\n%s: Debug mask = 0x%x\n", FS_name[index], FS_dbg_mask);
|
||
is = FS_rply_status_setup_and_send (skt, reply, KER__SUCCESS, 0,
|
||
NULL, &FS_bytes_put);
|
||
if (!is)
|
||
printf ("\n%s -- send of status reply failed.\n", FS_name[index]);
|
||
return is;
|
||
|
||
case SQHM_DECONFIG: /* Close down any servers and then deconfigure
|
||
** our slaves */
|
||
printf ("\n%s: De-configure", FS_name[index]);
|
||
if (!FS_cfgn_done) { /* Anything to do? */
|
||
printf (" -- already de-configured!\n");
|
||
is = FS_rply_status_setup_and_send (skt, reply, KER__SUCCESS, 0,
|
||
NULL, &FS_bytes_put);
|
||
}else if (index != 0) {
|
||
printf (" -- not issued to Master Server!\n");
|
||
is = FS_rply_status_setup_and_send (skt, reply, KER__BAD_STATE, 0,
|
||
"Not Master Server", &FS_bytes_put);
|
||
}else {
|
||
harshness = ntohl (rqst->u.decnfg.sub_code); /* Pick out "harshness" */
|
||
is = FS_close_down_offspring (harshness,
|
||
MAX_CLIENTS, FS_pids, FS_chld_exit_status,
|
||
&FS_cnt_SIGUSR1, FS_dbg_lev0, FS_p_names, "");
|
||
if (is) {
|
||
is = FS_deconfig_all (harshness);
|
||
if (is) {
|
||
printf (" done.\n");
|
||
FS_cfgn_done = False;
|
||
is = FS_rply_status_setup_and_send (skt, reply, KER__SUCCESS, 0,
|
||
NULL, &FS_bytes_put);
|
||
}else {
|
||
printf ("\nFailed! Problem deconfiguring slaves.\n");
|
||
is = FS_rply_status_setup_and_send (skt, reply, KER__BAD_STATE, is,
|
||
"Problem deconfiguring slaves", &FS_bytes_put);
|
||
}
|
||
}else {
|
||
printf ("\nFailed! Problem terminating children.\n");
|
||
is = FS_rply_status_setup_and_send (skt, reply, KER__BAD_STATE, is,
|
||
"Problem terminating children", &FS_bytes_put);
|
||
}
|
||
FS_free_memory (NULL); /* Release all reserved memory */
|
||
}
|
||
if (!is)
|
||
printf ("\n%s -- send of status reply failed.\n", FS_name[index]);
|
||
return is;
|
||
|
||
case SQHM_EXIT: /* Rundown */
|
||
printf ("\n%s: Run-down ...", FS_name[index]);
|
||
if (index != 0) {
|
||
printf (" -- not issued to Master Server!\n");
|
||
is = FS_rply_status_setup_and_send (skt, reply, KER__BAD_STATE, 0,
|
||
"Not SinqHM-master", &FS_bytes_put);
|
||
}else if (FS_cfgn_done) {
|
||
printf (" -- not issued to SinqHM-master!\n");
|
||
is = FS_rply_status_setup_and_send (skt, reply, KER__BAD_STATE, 0,
|
||
"Not SinqHM-master", &FS_bytes_put);
|
||
}else {
|
||
rqst->u.decnfg.sub_code = htonl (1); /* Set "harshness" = 1 */
|
||
is = FS_close_down_offspring (
|
||
ntohl (rqst->u.decnfg.sub_code), /* Pick out "harshness" */
|
||
MAX_CLIENTS, FS_pids, FS_chld_exit_status,
|
||
&FS_cnt_SIGUSR1, FS_dbg_lev0, FS_p_names, "");
|
||
if (is) {
|
||
if (FS_cfgn_done) {
|
||
printf (" deconfiguring ...");
|
||
is = FS_deconfig_all (1);
|
||
if (is) {
|
||
printf (" done.\n");
|
||
FS_cfgn_done = False;
|
||
is = FS_rply_status_setup_and_send (skt, reply, KER__SUCCESS, 0,
|
||
NULL, &FS_bytes_put);
|
||
}else {
|
||
printf (" WARNING: deconfig failed.\n");
|
||
is = FS_rply_status_setup_and_send (skt, reply, KER__BAD_STATE,
|
||
is, "Problem deconfiguring", &FS_bytes_put);
|
||
}
|
||
}
|
||
}else {
|
||
printf (" WARNING: problem terminating children.\n");
|
||
is = FS_rply_status_setup_and_send (skt, reply, KER__BAD_STATE, is,
|
||
"Problem terminating children", &FS_bytes_put);
|
||
}
|
||
FS_free_memory (NULL); /* Release all reserved memory */
|
||
}
|
||
if (!is)
|
||
printf ("\n%s -- send of status reply failed.\n", FS_name[index]);
|
||
return True;
|
||
|
||
case SQHM_IDENT: /* Give info on software identification. */
|
||
txt_len = IDENT_MSGE_LEN;
|
||
txt_offset = 0;
|
||
p_buff = calloc (txt_len, 1); /* Get a buffer for text info */
|
||
if (p_buff == NULL) {
|
||
printf ("\n%s -- SQHM_IDENT: failed to get buffer!\n",
|
||
FS_name[index]);
|
||
FS_rply_status_setup_and_send (skt, reply, KER__BAD_ALLOC, 0,
|
||
"Failed to get buffer for composing Ident", &FS_bytes_put);
|
||
return False;
|
||
}
|
||
time (&secs);
|
||
secs = secs - FS_start_time;
|
||
reply->u.ident.up_time = htonl (secs);
|
||
reply->u.ident.n_extra_bytes = htonl (IDENT_MSGE_LEN);
|
||
p_txt = p_buff;
|
||
|
||
reply->u.ident.offset_vxWorks_ident = htons (txt_offset);
|
||
StrJoin (p_txt, txt_len, vxWorksVersion, "");
|
||
i = strlen (p_txt) + 1;
|
||
txt_offset += i; p_txt += i; txt_len -= i;
|
||
|
||
reply->u.ident.offset_vxWorks_date = htons (txt_offset);
|
||
StrJoin (p_txt, txt_len, creationDate, "");
|
||
i = strlen (p_txt) + 1;
|
||
txt_offset += i; p_txt += i; txt_len -= i;
|
||
|
||
reply->u.ident.offset_instr = htons (txt_offset);
|
||
StrJoin (p_txt, txt_len, FS_inst, "");
|
||
i = strlen (p_txt) + 1;
|
||
txt_offset += i; p_txt += i; txt_len -= i;
|
||
|
||
reply->u.ident.offset_def_ident = htons (txt_offset);
|
||
StrJoin (p_txt, txt_len, FS_def_ident, "");
|
||
i = strlen (p_txt) + 1;
|
||
txt_offset += i; p_txt += i; txt_len -= i;
|
||
|
||
reply->u.ident.offset_sinqhm_main_ident = htons (txt_offset);
|
||
StrJoin (p_txt, txt_len, FS_main_ident, "");
|
||
i = strlen (p_txt) + 1;
|
||
txt_offset += i; p_txt += i; txt_len -= i;
|
||
|
||
reply->u.ident.offset_sinqhm_main_date = htons (txt_offset);
|
||
StrJoin (p_txt, txt_len, FS_main_date, "");
|
||
i = strlen (p_txt) + 1;
|
||
txt_offset += i; p_txt += i; txt_len -= i;
|
||
|
||
reply->u.ident.offset_sinqhm_server_ident = htons (txt_offset);
|
||
StrJoin (p_txt, txt_len, FS_serv_ident, "");
|
||
i = strlen (p_txt) + 1;
|
||
txt_offset += i; p_txt += i; txt_len -= i;
|
||
|
||
reply->u.ident.offset_sinqhm_server_date = htons (txt_offset);
|
||
StrJoin (p_txt, txt_len, FS_serv_date, "");
|
||
i = strlen (p_txt) + 1;
|
||
txt_offset += i; p_txt += i; txt_len -= i;
|
||
|
||
reply->u.ident.offset_sinqhm_filler_ident = htons (txt_offset);
|
||
StrJoin (p_txt, txt_len, "", "");
|
||
i = strlen (p_txt) + 1;
|
||
txt_offset += i; p_txt += i; txt_len -= i;
|
||
|
||
reply->u.ident.offset_sinqhm_filler_date = htons (txt_offset);
|
||
StrJoin (p_txt, txt_len, "", "");
|
||
i = strlen (p_txt) + 1;
|
||
txt_offset += i; p_txt += i; txt_len -= i;
|
||
|
||
reply->u.ident.offset_sinqhm_routines_ident = htons (txt_offset);
|
||
StrJoin (p_txt, txt_len, FS_rout_ident, "");
|
||
i = strlen (p_txt) + 1;
|
||
txt_offset += i; p_txt += i; txt_len -= i;
|
||
|
||
reply->u.ident.offset_sinqhm_routines_date = htons (txt_offset);
|
||
StrJoin (p_txt, txt_len, FS_rout_date, "");
|
||
i = strlen (p_txt) + 1;
|
||
txt_offset += i; p_txt += i; txt_len -= i;
|
||
|
||
is = FS_rply_status_send (skt, reply, &FS_bytes_put);
|
||
/*
|
||
** Now send the data
|
||
*/
|
||
p_txt = p_buff;
|
||
bytes_to_go = IDENT_MSGE_LEN;
|
||
while (bytes_to_go > 0) {
|
||
i = (bytes_to_go > pkt_size) ? pkt_size : bytes_to_go;
|
||
is = send (skt, p_txt, i, 0);
|
||
if (is > 0) {
|
||
FS_bytes_put += is;
|
||
bytes_to_go -= is;
|
||
p_txt += is;
|
||
}else {
|
||
free (p_buff);
|
||
printf ("\n%s -- SQHM_IDENT: failed to send extra data!\n",
|
||
FS_name[index]);
|
||
return False; /* Fatal error on send */
|
||
}
|
||
}
|
||
free (p_buff);
|
||
return True;
|
||
|
||
case SQHM_PROJECT: /* Read a projected "rectangle" of the HM. */
|
||
if (!FS_cfgn_done) { /* Check we've been configured */
|
||
printf ("\n%s -- projecting but not yet configured!\n", FS_name[index]);
|
||
is = FS_rply_status_setup_and_send (skt, reply, KER__BAD_STATE, 0,
|
||
"Not configured", &FS_bytes_put);
|
||
return False;
|
||
}else {
|
||
if (FS_dbg_lev0) printf ("\n%s -- projecting ...", FS_name[index]);
|
||
my_sub_code = ntohl (rqst->u.project.sub_code);
|
||
my_x_lo = ntohl (rqst->u.project.x_lo);
|
||
my_nx = ntohl (rqst->u.project.nx);
|
||
my_y_lo = ntohl (rqst->u.project.y_lo);
|
||
my_ny = ntohl (rqst->u.project.ny);
|
||
my_xdim = ntohl (rqst->u.project.xdim);
|
||
my_h_slct = ntohl (rqst->u.project.nhist);
|
||
is = FS_do_project (index, reply, skt, pkt_size,
|
||
my_sub_code, my_x_lo, my_nx, my_y_lo, my_ny, my_xdim, my_h_slct);
|
||
if (!is) {
|
||
printf ("\n%s -- SQHM_PROJECT fatal error sending status reply or "
|
||
"histo data.\n", FS_name[index]);
|
||
}else {
|
||
if (FS_dbg_lev0) printf (" done.\n");
|
||
}
|
||
return is;
|
||
}
|
||
|
||
case SQHM_READ: /* Read a section of the HM. */
|
||
if (!FS_cfgn_done) { /* Check we've been configured */
|
||
printf ("\n%s -- reading but not yet configured!\n", FS_name[index]);
|
||
is = FS_rply_status_setup_and_send (skt, reply, KER__BAD_STATE, 0,
|
||
"Not configured", &FS_bytes_put);
|
||
return False;
|
||
}else {
|
||
if (FS_dbg_lev0) printf ("\n%s -- reading ...", FS_name[index]);
|
||
my_hist_no = ntohl (rqst->u.read.hist_no);
|
||
my_first_bin = ntohl (rqst->u.read.first_bin);
|
||
my_nbins = ntohl (rqst->u.read.n_bins);
|
||
is = FS_do_read (index, reply, skt, pkt_size,
|
||
my_nbins, my_first_bin, my_hist_no);
|
||
if (!is) {
|
||
printf ("\n%s -- SQHM_READ fatal error sending status reply or "
|
||
"histo data.\n", FS_name[index]);
|
||
}else {
|
||
if (FS_dbg_lev0) printf (" done.\n");
|
||
}
|
||
return is;
|
||
}
|
||
|
||
case SQHM_SELECT: /* SQHM_SELECT still needs to be programmed. */
|
||
printf ("\n%s: Select ...", FS_name[index]);
|
||
is = FS_rply_status_setup_and_send (skt, reply, KER__BAD_VALUE, 0,
|
||
"Not yet available!", &FS_bytes_put);
|
||
if (!is) {
|
||
printf ("\n%s -- send of status reply failed.\n", FS_name[index]);
|
||
}else {
|
||
printf (" not yet implemented!\n");
|
||
}
|
||
return is;
|
||
|
||
case SQHM_STATUS: /* Get-Status request */
|
||
if (FS_dbg_lev0) printf ("\n%s: Status ...", FS_name[index]);
|
||
/*
|
||
** Build up info
|
||
*/
|
||
reply->status = htonl (KER__SUCCESS); /* Indicate success */
|
||
strcpy ((char *) &reply->sub_status, /* Set up the Ident */
|
||
SINQHM_DEF_ID); /* This does not need htonl! */
|
||
reply->u.status.max_n_hists = htonl (N_HISTS_MAX);
|
||
reply->u.status.max_num_bins = htonl (N_BINS_MAX + 1);
|
||
reply->u.status.max_srvrs = MAX_CLIENTS;
|
||
reply->u.status.max_block = htonl (memFindMax ()); /* Max free mem */
|
||
if (!FS_cfgn_done) {
|
||
reply->u.status.cfg_state = 0;
|
||
reply->u.status.n_hists = 0;
|
||
reply->u.status.curr_hist = 0;
|
||
reply->u.status.num_bins = 0;
|
||
reply->u.status.act_srvrs = 0;
|
||
reply->u.status.bytes_per_bin = 0;
|
||
reply->u.status.compress = 0;
|
||
reply->u.status.daq_now = 0;
|
||
reply->u.status.filler_mask = 0;
|
||
reply->u.status.tsi_status = 0;
|
||
reply->u.status.flags = 0;
|
||
reply->u.status.dt_or_dts.both = 0;
|
||
reply->u.status.num_bad_events = 0;
|
||
}else {
|
||
reply->u.status.cfg_state = htonl (FS_mode_ALL);
|
||
reply->u.status.n_hists = htonl (FS_hi_cntr - FS_lo_cntr + 1);
|
||
reply->u.status.curr_hist = htons (0);
|
||
reply->u.status.num_bins = htonl (FS_hi_bin - FS_lo_bin + 1);
|
||
|
||
for (j = 0, i = 1; i <= MAX_CLIENTS; i++) if (FS_pids[i] != 0) j++;
|
||
reply->u.status.act_srvrs = j;
|
||
|
||
reply->u.status.bytes_per_bin = FS_bpb;
|
||
reply->u.status.compress = FS_compress;
|
||
reply->u.status.daq_now = htons (FS_dsbl_mask);
|
||
reply->u.status.filler_mask = htons (FS_srv_masks[0]);
|
||
reply->u.status.tsi_status = htonl (0);
|
||
reply->u.status.flags = htonl (0);
|
||
reply->u.status.dt_or_dts.both = htonl (0);
|
||
reply->u.status.num_bad_events = htonl (0);
|
||
}
|
||
time (&secs);
|
||
secs = secs - FS_start_time;
|
||
reply->u.status.up_time = htonl (secs);
|
||
|
||
is = FS_rply_status_send (skt, reply, &FS_bytes_put);
|
||
if (FS_dbg_lev0) {
|
||
if (!is) {
|
||
printf ("\n%s -- send of status reply failed.\n", FS_name[index]);
|
||
}else {
|
||
printf (" has been sent.\n");
|
||
}
|
||
}
|
||
return is;
|
||
|
||
case SQHM_WRITE: /* Write a section of the HM.
|
||
**
|
||
** NOTE: always call FS_do_write, even if not configured
|
||
** ==== since network data has always to be read.
|
||
*/
|
||
printf ("\n%s: writing ...", FS_name[index]);
|
||
my_hist_no = ntohl (rqst->u.write.hist_no);
|
||
my_first_bin = ntohl (rqst->u.write.first_bin);
|
||
my_nbins = ntohl (rqst->u.write.n_bins);
|
||
my_bytes_per_bin = ntohl (rqst->u.write.bytes_per_bin);
|
||
is = FS_do_write (index, rqst, reply, skt, pkt_size,
|
||
my_nbins, my_first_bin, my_bytes_per_bin, my_hist_no);
|
||
if (!is) {
|
||
printf ("\n%s -- send of status reply failed.\n", FS_name[index]);
|
||
}else {
|
||
printf (" done.\n");
|
||
}
|
||
return is;
|
||
|
||
case SQHM_ZERO:
|
||
if (!FS_cfgn_done) { /* Check we've been configured */
|
||
printf ("\n%s -- zeroing but not yet configured!\n", FS_name[index]);
|
||
is = FS_rply_status_setup_and_send (skt, reply, KER__BAD_STATE, 0,
|
||
"Not configured", &FS_bytes_put);
|
||
return False;
|
||
}else {
|
||
printf ("\n%s -- zeroing ...", FS_name[index]);
|
||
|
||
my_hist_no = ntohl (rqst->u.zero.hist_no);
|
||
my_first_bin = ntohl (rqst->u.zero.first_bin);
|
||
my_nbins = ntohl (rqst->u.zero.n_bins);
|
||
|
||
FS_do_zero (reply, index, my_nbins, my_first_bin, my_hist_no);
|
||
is = FS_rply_status_send (skt, reply, &FS_bytes_put);
|
||
if (!is) {
|
||
printf ("\n%s -- send of status reply failed.\n", FS_name[index]);
|
||
}else {
|
||
printf (" done.\n");
|
||
}
|
||
return is;
|
||
}
|
||
|
||
default:
|
||
printf ("\n%s: Unrecognised command received ...\n", FS_name[index]);
|
||
is = FS_rply_status_setup_and_send (skt, reply, KER__BAD_VALUE, 0,
|
||
"Unrecognised command!", &FS_bytes_put);
|
||
if (!is) {
|
||
printf ("\n%s -- send of status reply failed.\n", FS_name[index]);
|
||
}else {
|
||
printf (" it has been acknowledged.\n");
|
||
}
|
||
return is;
|
||
}
|
||
printf ("\nSoftware error in do_command - switch statement completed!\n");
|
||
return False;
|
||
}
|
||
/*
|
||
**--------------------------------------------------------------------------
|
||
** FS_do_config: ...
|
||
*/
|
||
int FS_do_config (
|
||
/* ============
|
||
*/ int skt,
|
||
struct req_buff_struct *request,
|
||
struct rply_buff_struct *reply) {
|
||
|
||
int i, n_bytes_got, iret, return_status;
|
||
uint bytes_needed, n_extra, n_edges, n_banks;
|
||
uint sizeof_edge_arr, n_bins, flag;
|
||
uint lo_cntr, hi_cntr, n_cntrs, slv_lo_cntr, slv_hi_cntr;
|
||
char *p_addr;
|
||
struct tof_bank *p_bank;
|
||
struct req_buff_struct *my_rqu;
|
||
struct rply_buff_struct my_rply;
|
||
|
||
FS_mode_ALL = ntohl (request->u.cnfg.mode); /* The histogramming mode */
|
||
|
||
FS_mode = FS_mode_ALL & (~SQHM__SUB_MODE_MSK);
|
||
FS_mode_DEBUG = FS_mode_ALL & SQHM__DEBUG;
|
||
FS_mode_UD = FS_mode_ALL & SQHM__UD;
|
||
FS_mode_BO = FS_mode_ALL & SQHM__BO_MSK;
|
||
FS_mode_STROBO = FS_mode_ALL & SQHM__STROBO;
|
||
FS_mode_REFLECT = FS_mode_ALL & SQHM__REFLECT;
|
||
FS_mode_NO_STAT = FS_mode_ALL & SQHM__NO_STAT;
|
||
|
||
if (FS_mode != SQHM__TOF) { /* The mode must be TOF */
|
||
printf ("\nFS_do_config: mode is not TOF\n");
|
||
return False;
|
||
}
|
||
/*
|
||
** For complicated configurations, there may be more config
|
||
** data to be read. If so n_extra_bytes will be non-zero.
|
||
*/
|
||
n_extra = ntohl (request->u.cnfg.u.tof.n_extra_bytes);
|
||
if (n_extra != 0) {
|
||
/*
|
||
** There is extra data to be read. Get buffer space for the
|
||
** extra stuff plus space to copy over what has already been
|
||
** read so that everything is in a contiguous buffer.
|
||
*/
|
||
bytes_needed = n_extra + sizeof (*request);
|
||
bytes_needed = (bytes_needed + 3) & (~3); /* Round up to multiple of 4 */
|
||
p_addr = malloc (bytes_needed);
|
||
if (p_addr == NULL) {
|
||
printf ("\nFS_do_config:"
|
||
" cannot allocate memory for extra config data!\n");
|
||
net_flush (skt, n_extra);
|
||
rply_status_setup (reply, KER__BAD_ALLOC, 0,
|
||
"Failed to get buffer for extra config data");
|
||
return False;
|
||
}
|
||
my_rqu = (struct req_buff_struct *) p_addr;
|
||
memcpy (p_addr, request, sizeof (*request)); /* Copy in what has already
|
||
** been read. */
|
||
bytes_needed = n_extra; /* And read the rest */
|
||
p_addr += sizeof (*request);
|
||
while (bytes_needed > 0) {
|
||
n_bytes_got = recv (skt, p_addr, bytes_needed, 0);
|
||
if (n_bytes_got <= 0) break;
|
||
FS_bytes_got += n_bytes_got;
|
||
bytes_needed -= n_bytes_got;
|
||
p_addr += n_bytes_got;
|
||
}
|
||
if (n_bytes_got < 0) {
|
||
printf ("\n"
|
||
"%s -- R/W-Socket recv error\n"
|
||
"%s -- Connection will be closed.\n", FS_name[0], FS_name[0]);
|
||
rply_status_setup (reply, KER__BAD_VALUE, 0, "recv failed");
|
||
free (my_rqu);
|
||
return False;
|
||
}
|
||
}else {
|
||
my_rqu = request;
|
||
}
|
||
|
||
n_bins = ntohl (my_rqu->u.cnfg.u.tof.edge_0.n_bins);
|
||
flag = ntohl (my_rqu->u.cnfg.u.tof.edge_0.flag);
|
||
if ((flag & FLAG__VAR_BIN) != 0) {
|
||
sizeof_edge_arr = OffsetOf (struct tof_edge_arr, edges) +
|
||
((n_bins + 1) * sizeof (uint));
|
||
FS_compress = 0;
|
||
}else {
|
||
sizeof_edge_arr = sizeof (struct tof_edge_arr);
|
||
FS_compress = ntohl (my_rqu->u.cnfg.u.tof.edge_0.edges[1]) -
|
||
ntohl (my_rqu->u.cnfg.u.tof.edge_0.edges[0]);
|
||
}
|
||
p_bank = (struct tof_bank *) (
|
||
(char *) &my_rqu->u.cnfg.u.tof.edge_0 + sizeof_edge_arr);
|
||
|
||
|
||
n_edges = ntohs (my_rqu->u.cnfg.u.tof.n_edges);
|
||
n_banks = ntohs (my_rqu->u.cnfg.u.tof.n_banks);
|
||
if ((n_edges != 1) || (n_banks != 1)) {
|
||
printf ("\nFS_do_config: configuration is too complex.\n");
|
||
return False;
|
||
}
|
||
lo_cntr = ntohl (p_bank->first);
|
||
n_cntrs = ntohl (p_bank->n_cntrs);
|
||
hi_cntr = lo_cntr + n_cntrs -1;
|
||
/*
|
||
** Now loop sending the configuration request to
|
||
** all slaves.
|
||
*/
|
||
return_status = True; /* Assume all will be OK */
|
||
for (i = 0; i < FS_n_slaves; i++) {
|
||
if (FS_slaves[i] != NULL) {
|
||
slv_lo_cntr = (FS_lo_det[i] > lo_cntr) ? FS_lo_det[i] : lo_cntr;
|
||
slv_hi_cntr = (FS_hi_det[i] < hi_cntr) ? FS_hi_det[i] : hi_cntr;
|
||
if (slv_hi_cntr >= slv_lo_cntr) {
|
||
FS_slv_active[i] = True;
|
||
p_bank->first = htonl (slv_lo_cntr - FS_lo_det[i]);
|
||
p_bank->n_cntrs = htonl (slv_hi_cntr - slv_lo_cntr + 1);
|
||
iret = FS_send_cmnd_to_mstr (&FS_rmt_socknam[i],
|
||
my_rqu, (sizeof (*request) + n_extra),
|
||
&my_rply, &FS_bytes_got, &FS_bytes_put);
|
||
if (iret && (ntohl (my_rply.status) != KER__SUCCESS)) {
|
||
reply->status = my_rply.status;
|
||
reply->sub_status = my_rply.sub_status;
|
||
StrJoin (reply->u.message, sizeof (reply->u.message),
|
||
FS_slaves[i], ": ");
|
||
StrJoin (reply->u.message, sizeof (reply->u.message),
|
||
reply->u.message, my_rply.u.message);
|
||
FS_slv_active[i] = False;
|
||
return_status = False;
|
||
break;
|
||
}
|
||
}else {
|
||
FS_slv_active[i] = False;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (!return_status) { /* If any error, force deconfig */
|
||
FS_deconfig_all (1);
|
||
return return_status;
|
||
}
|
||
|
||
FS_lo_cntr = lo_cntr;
|
||
FS_hi_cntr = hi_cntr;
|
||
FS_lo_bin = 0;
|
||
FS_hi_bin = n_bins - 1;
|
||
FS_bpb = ntohl (p_bank->bytes_per_bin);
|
||
FS_totl_bytes = FS_bpb * (FS_hi_cntr - FS_lo_cntr + 1) *
|
||
(FS_hi_bin - FS_lo_bin + 1);
|
||
|
||
if (n_extra != 0) free (my_rqu);
|
||
return return_status;
|
||
}
|
||
/*
|
||
**--------------------------------------------------------------------------
|
||
** FS_do_daq: Handle an SQHM_DAQ command.
|
||
*/
|
||
int FS_do_daq (
|
||
/* =========
|
||
*/ int indx,
|
||
int sub_cmnd,
|
||
struct req_buff_struct *request,
|
||
struct rply_buff_struct *reply) {
|
||
|
||
int i, iret, all_ok = True;
|
||
|
||
if (sub_cmnd == DAQ__TST) { /* DAQ__TST is special - we just give the ..
|
||
** .. caller a snapshot of our status ..
|
||
** .. without invoking our slaves. */
|
||
reply->status = htonl (KER__SUCCESS);
|
||
reply->u.daq.daq_was = htons (FS_dsbl_mask);
|
||
reply->u.daq.filler_mask = htons (FS_srv_masks[0]);
|
||
reply->u.daq.server_mask = htons (FS_srv_masks[indx]);
|
||
reply->u.daq.daq_now = reply->u.daq.daq_was;
|
||
}else {
|
||
/*
|
||
** Claim the sem to avoid race conditions with other threads
|
||
*/
|
||
if (FS_use_sem_tmo) {
|
||
iret = semTake (FS_sem_daq, FS_sem_tmo);
|
||
}else {
|
||
iret = semTake (FS_sem_daq, WAIT_FOREVER);
|
||
}
|
||
/*
|
||
** Loop sending the SQHM_DAQ command to active slaves
|
||
*/
|
||
request->bigend = htonl (0x12345678);
|
||
request->cmnd = htonl (SQHM_DAQ);
|
||
request->u.daq.sub_cmnd = htonl (sub_cmnd);
|
||
for (i = 0; i < FS_n_slaves; i++) {
|
||
if (FS_slv_active[i]) {
|
||
if (indx == 0) { /* If we are the master-server, send it to the
|
||
** master-servers in the slaves. */
|
||
iret = FS_send_cmnd_to_mstr (&FS_rmt_socknam[i],
|
||
request, sizeof (*request), reply,
|
||
&FS_bytes_got, &FS_bytes_put);
|
||
if (!iret || (ntohl (reply->status) != KER__SUCCESS)) all_ok=False;
|
||
}else {
|
||
iret = rqst_send_get (FS_skt[indx][i], request, sizeof (*request),
|
||
reply, sizeof (*reply),
|
||
&FS_bytes_got, &FS_bytes_put, FS_name[indx]);
|
||
if (!iret || (ntohl (reply->status) != KER__SUCCESS)) all_ok=False;
|
||
}
|
||
}
|
||
}
|
||
if (!all_ok) { /* If error, go no further! */
|
||
semGive (FS_sem_daq);
|
||
return all_ok;
|
||
}
|
||
reply->status = htonl (KER__SUCCESS);
|
||
reply->u.daq.daq_was = htons (FS_dsbl_mask);
|
||
reply->u.daq.filler_mask = htons (FS_srv_masks[0]);
|
||
reply->u.daq.server_mask = htons (FS_srv_masks[indx]);
|
||
switch (sub_cmnd) {
|
||
case DAQ__CLR:
|
||
FS_dsbl_mask &= (~FS_srv_masks[indx]); /* Clear user's mask bit. */
|
||
break;
|
||
case DAQ__GO:
|
||
FS_dsbl_mask &= (~FS_srv_masks[0]); /* Clear "filler's" mask bit. */
|
||
break;
|
||
case DAQ__INH:
|
||
FS_dsbl_mask |= FS_srv_masks[indx]; /* Set user's mask bit */
|
||
break;
|
||
case DAQ__STOP:
|
||
FS_dsbl_mask |= FS_srv_masks[0]; /* Set "filler's" mask bit. */
|
||
}
|
||
reply->u.daq.daq_now = htons (FS_dsbl_mask); /* Complete the status
|
||
** response message */
|
||
iret = semGive (FS_sem_daq); /* Release the semaphore */
|
||
}
|
||
return all_ok;
|
||
}
|
||
/*
|
||
**--------------------------------------------------------------------------
|
||
** FS_do_project: Read a "rectangular" region of Hist Mem and send it
|
||
** to the client.
|
||
*/
|
||
int FS_do_project (
|
||
/* =============
|
||
*/ int index,
|
||
struct rply_buff_struct *rply_bf,
|
||
int rw_skt,
|
||
int pkt_size,
|
||
uint sub_code,
|
||
uint x_lo,
|
||
uint nx,
|
||
uint y_lo,
|
||
uint ny,
|
||
uint xdim,
|
||
uint h_slct) {
|
||
/*
|
||
** Read a "rectangular" region of Hist Mem and send it
|
||
** to the client.
|
||
*/
|
||
uint my_bin_lo, my_bin_hi;
|
||
uint my_cntr_lo, my_cntr_hi;
|
||
int i, is, nput, my_daq_save;
|
||
uint my_nbins, bins_to_go, bytes_in_buff, bytes_to_go;
|
||
uchar *buff_pntr;
|
||
char recd[132], *nxt;
|
||
struct req_buff_struct my_rqst;
|
||
struct rply_buff_struct my_rply;
|
||
|
||
register union {
|
||
void *base;
|
||
uchar *ch;
|
||
usint *i2;
|
||
uint *i4;
|
||
} my_pntr0, my_pntr1;
|
||
|
||
rply_status_setup (rply_bf, KER__BAD_VALUE, 0, "Bad argument"); /* Assume ..
|
||
** .. we shall find a bad arg */
|
||
/*--------------------------------------------------------------------
|
||
** There's no need to test the hist mode; it must be SQHM_TOF because
|
||
** SQHM_CONFIG rejects anything else. So, start by checking arguments.
|
||
*/
|
||
if ((sub_code & PROJECT__1_DIM) != 0) {
|
||
printf ("\n%s -- SQHM_PROJECT: SQHM__TOF+PROJECT__1_DIM not yet "
|
||
"implemented!\n", FS_name[index]);
|
||
is = FS_rply_status_setup_and_send (rw_skt, rply_bf, KER__BAD_VALUE, 0,
|
||
"Not yet implemented", &FS_bytes_put);
|
||
return OK;
|
||
}
|
||
/* Check the arguments */
|
||
/* Check that counter numbers are in range */
|
||
my_cntr_lo = y_lo;
|
||
if ((my_cntr_lo < FS_lo_cntr) ||
|
||
(my_cntr_lo > FS_hi_cntr)) {
|
||
printf ("\n%s -- SQHM_PROJECT: Bad y_lo!\n", FS_name[index]);
|
||
is = FS_rply_status_send (rw_skt, rply_bf, &FS_bytes_put);
|
||
return OK;
|
||
}
|
||
my_cntr_hi = (ny != 0) ? (y_lo + ny - 1) : FS_hi_cntr;
|
||
if ((my_cntr_hi < my_cntr_lo) || (my_cntr_hi > FS_hi_cntr)) {
|
||
printf ("\n%s -- SQHM_PROJECT: Bad ny!\n", FS_name[index]);
|
||
is = FS_rply_status_send (rw_skt, rply_bf, &FS_bytes_put);
|
||
return OK;
|
||
}
|
||
/* Check that bin numbers are in range */
|
||
my_bin_lo = x_lo;
|
||
if ((my_bin_lo < FS_lo_bin) ||
|
||
(my_bin_lo > FS_hi_bin)) {
|
||
printf ("\n%s -- SQHM_PROJECT: Bad x_lo!\n", FS_name[index]);
|
||
is = FS_rply_status_send (rw_skt, rply_bf, &FS_bytes_put);
|
||
return OK;
|
||
}
|
||
my_bin_hi = (nx != 0) ?
|
||
(x_lo + nx - 1) : FS_hi_bin;
|
||
if ((my_bin_hi < my_bin_lo) ||
|
||
(my_bin_hi > FS_hi_bin)) {
|
||
printf ("\n%s -- SQHM_PROJECT: Bad nx!\n", FS_name[index]);
|
||
is = FS_rply_status_send (rw_skt, rply_bf, &FS_bytes_put);
|
||
return OK;
|
||
}
|
||
/*
|
||
** All the arguments have been checked. Reserve some space
|
||
** for projecting the data. The amount of space that we
|
||
** need for the projection depends on whether the
|
||
** projection is onto the x-axis or y-axis.
|
||
*/
|
||
my_nbins = ((sub_code & PROJECT__ON_Y) == 0) ?
|
||
(my_bin_hi - my_bin_lo + 1) : (my_cntr_hi - my_cntr_lo + 1);
|
||
|
||
my_pntr0.base = calloc (my_nbins, sizeof (uint));
|
||
my_pntr1.base = calloc (my_nbins, sizeof (uint));
|
||
if ((my_pntr0.base == NULL) || (my_pntr1.base == NULL)) {
|
||
printf ("\n%s -- SQHM_PROJECT: failed to get buffer!\n",
|
||
FS_name[index]);
|
||
FS_rply_status_setup_and_send (rw_skt, rply_bf, KER__BAD_ALLOC, 0,
|
||
"Failed to get buffer for projecting data", &FS_bytes_put);
|
||
return OK;
|
||
free (my_pntr1.base);
|
||
}
|
||
/*-----------------------------------------------------
|
||
** We got some buffer space so inhibit data acqu ...
|
||
*/
|
||
my_daq_save = FS_dsbl_mask & FS_srv_masks[index]; /* Remember the ..
|
||
** .. state of our inhibit bit and disable data acq
|
||
** .. if not already disabled by us. This is necessary
|
||
** .. to prevent data "skewing" as we read out our
|
||
** .. 3 slaves. */
|
||
if (my_daq_save == 0) FS_do_daq (index, DAQ__INH, &my_rqst, &my_rply);
|
||
/*-----------------------------------------------------
|
||
** ... then do the projection ...
|
||
*/
|
||
bins_to_go = FS_project_hm (index, pkt_size,
|
||
my_pntr0.base, my_pntr1.base, my_nbins,
|
||
sub_code, my_cntr_lo, my_cntr_hi, my_bin_lo, my_bin_hi);
|
||
if (bins_to_go <= 0) {
|
||
if (my_daq_save == 0) FS_do_daq (index, DAQ__CLR, &my_rqst, &my_rply);
|
||
perror (StrJoin (recd, sizeof (recd),
|
||
FS_name[index], "/FS_do_project: FS_project_hm error"));
|
||
free (my_pntr0.base);
|
||
free (my_pntr1.base);
|
||
return False;
|
||
}
|
||
/*-----------------------------------------------------
|
||
** ... projection complete so let Filler continue and
|
||
** send data back to client.
|
||
*/
|
||
if (my_daq_save == 0) FS_do_daq (index, DAQ__CLR, &my_rqst, &my_rply);
|
||
|
||
rply_bf->u.project.n_bins = htonl (my_nbins);
|
||
rply_bf->u.project.bytes_per_bin = htonl (sizeof (uint));
|
||
rply_bf->u.project.cnts_lo = htonl (0);
|
||
rply_bf->u.project.cnts_hi = htonl (0);
|
||
|
||
if (rply_bf->bigend != 0x12345678) { /* If byte swapping needed, ...
|
||
** .. then swap them! */
|
||
for (i = 0; i < my_nbins; i++) my_pntr0.i4[i] = htonl (my_pntr0.i4[i]);
|
||
}
|
||
|
||
is = FS_rply_status_setup_and_send (rw_skt, rply_bf, KER__SUCCESS, 0,
|
||
NULL, &FS_bytes_put);
|
||
|
||
bytes_to_go = my_nbins * sizeof (uint);
|
||
buff_pntr = (uchar *) my_pntr0.base;
|
||
|
||
while (bytes_to_go > 0) {
|
||
nput = (bytes_to_go > pkt_size) ? pkt_size : bytes_to_go;
|
||
is = send (rw_skt, buff_pntr, nput, 0);
|
||
if (is > 0) {
|
||
FS_bytes_put += is;
|
||
bytes_to_go -= is;
|
||
buff_pntr += is;
|
||
}else {
|
||
free (my_pntr0.base);
|
||
free (my_pntr1.base);
|
||
return ERROR; /* Fatal error on send */
|
||
}
|
||
}
|
||
free (my_pntr0.base); /* Release our bit of memory */
|
||
free (my_pntr1.base);
|
||
return True;
|
||
}
|
||
/*
|
||
**--------------------------------------------------------------------------
|
||
** FS_do_read: Read a consecutive region of 'nbins' bins of the
|
||
** Hist Mem starting with bin 'first' and send it to
|
||
** the client.
|
||
*/
|
||
int FS_do_read (
|
||
/* ==========
|
||
*/ int index,
|
||
struct rply_buff_struct *rply_bf,
|
||
int rw_skt,
|
||
int pkt_size,
|
||
uint nbins,
|
||
uint first,
|
||
uint hist_no) {
|
||
|
||
register int i, my_fstbin, my_topbin;
|
||
int is, status, bytes_to_go, nput, nxtbin, nb;
|
||
int my_daq_save;
|
||
uint maxbins, my_nbins, bins_in_buff;
|
||
uint nxtbin_to_send, nbins_to_send, bytes_in_buff;
|
||
uint bins_to_go, lastbin;
|
||
struct req_buff_struct my_rqst;
|
||
struct rply_buff_struct my_rply;
|
||
uchar *buff_pntr, *last_byte, *nxt;
|
||
uchar buff[pkt_size];
|
||
|
||
register union {
|
||
void *base;
|
||
uchar *ch;
|
||
usint *i2;
|
||
uint *i4;
|
||
} my_pntr, hm_pntr;
|
||
/*--------------------------------------------------------------------
|
||
** There's no need to test the hist mode; it must be SQHM_TOF because
|
||
** SQHM_CONFIG rejects anything else. So, start by checking arguments.
|
||
*/
|
||
maxbins = (FS_hi_cntr - FS_lo_cntr + 1) * (FS_hi_bin - FS_lo_bin + 1);
|
||
/***************************************************************/
|
||
/***************************************************************/
|
||
if ((hist_no == -1) || (hist_no == 0)) {
|
||
/* Regard the histograms as 1 long array */
|
||
if ((first == -1) && (nbins == -1)) {
|
||
/* The user just wants to read everything */
|
||
my_fstbin = 0;
|
||
my_nbins = maxbins;
|
||
}else {
|
||
/* The user wants a part of the histogram data */
|
||
if (first >= maxbins) {
|
||
if (FS_dbg_lev0) printf (
|
||
"\n%s -- SQHM_READ: bad first_bin %d!\n", FS_name[index], first);
|
||
is = FS_rply_status_setup_and_send (rw_skt, rply_bf, KER__BAD_VALUE,
|
||
0, "\"first_bin\" too big", &FS_bytes_put);
|
||
return is;
|
||
}else if ((nbins > maxbins) || ((first + nbins) > maxbins)) {
|
||
if (FS_dbg_lev0) printf (
|
||
"\n%s -- SQHM_READ: bad n_bins %d!\n", FS_name[index], nbins);
|
||
is = FS_rply_status_setup_and_send (rw_skt, rply_bf, KER__BAD_VALUE,
|
||
0, "\"n_bins\" too big", &FS_bytes_put);
|
||
return is;
|
||
}
|
||
my_fstbin = first;
|
||
my_nbins = nbins;
|
||
}
|
||
}else {
|
||
/* The user wants a part of the histogram of a single counter */
|
||
if ((hist_no < FS_lo_cntr) || (hist_no > FS_hi_cntr)) {
|
||
if (FS_dbg_lev0) printf (
|
||
"\n%s -- SQHM_READ: bad hist_no!\n", FS_name[index]);
|
||
is = FS_rply_status_setup_and_send (rw_skt, rply_bf, KER__BAD_VALUE,
|
||
0, "\"hist_no\" out of range", &FS_bytes_put);
|
||
return is;
|
||
}else if ((first < FS_lo_bin) || (first > FS_hi_bin)) {
|
||
if (FS_dbg_lev0) printf (
|
||
"\n%s -- SQHM_READ: bad first_bin!\n", FS_name[index]);
|
||
is = FS_rply_status_setup_and_send (rw_skt, rply_bf, KER__BAD_VALUE,
|
||
0, "\"first_bin\" out of range", &FS_bytes_put);
|
||
return is;
|
||
}else if ((nbins > (FS_hi_bin - FS_lo_bin + 1)) ||
|
||
((first + nbins) > (FS_hi_bin + 1))) {
|
||
if (FS_dbg_lev0) printf (
|
||
"\n%s -- SQHM_READ: bad n_bins!\n", FS_name[index]);
|
||
is = FS_rply_status_setup_and_send (rw_skt, rply_bf, KER__BAD_VALUE,
|
||
0, "\"n_bins\" out of range", &FS_bytes_put);
|
||
return is;
|
||
}
|
||
my_fstbin = (hist_no - FS_lo_cntr) * (FS_hi_bin - FS_lo_bin + 1) + first;
|
||
my_nbins = nbins;
|
||
}
|
||
/***************************************************************/
|
||
/*
|
||
** The args are OK.
|
||
** Set up fixed buffer to do transfer
|
||
*/
|
||
my_pntr.base = NULL;
|
||
my_pntr.base = readBuffer;
|
||
bins_in_buff = READBUFSIZE/FS_bpb;
|
||
|
||
if (my_pntr.base == NULL ) {
|
||
if (FS_dbg_lev0) printf (
|
||
"\n%s -- SQHM_READ: no buffer space available!\n",
|
||
FS_name[index]);
|
||
is = FS_rply_status_setup_and_send (rw_skt, rply_bf, KER__BAD_VALUE,
|
||
0, "No buffer space", &FS_bytes_put);
|
||
return is;
|
||
}
|
||
/*
|
||
** The args are OK and we have some buffer space.
|
||
** Tell client he's about to get some data!
|
||
*/
|
||
rply_bf->u.read.first_bin = htonl (my_fstbin);
|
||
rply_bf->u.read.n_bins = htonl (my_nbins);
|
||
rply_bf->u.read.bytes_per_bin = htonl (FS_bpb);
|
||
rply_bf->u.read.cnts_lo = 0; /* \ cnts_lo and cnts_hi not */
|
||
rply_bf->u.read.cnts_hi = 0; /* / yet implemented */
|
||
is = FS_rply_status_setup_and_send (rw_skt, rply_bf, KER__SUCCESS,
|
||
0, NULL, &FS_bytes_put);
|
||
|
||
my_daq_save = FS_dsbl_mask & FS_srv_masks[index]; /* Remember the ..
|
||
** .. state of our inhibit bit and disable data acq
|
||
** .. if not already disabled by us. This is necessary
|
||
** .. to prevent data "skewing" as we read out our
|
||
** .. 3 slaves. */
|
||
if (my_daq_save == 0) FS_do_daq (index, DAQ__INH, &my_rqst, &my_rply);
|
||
nxtbin_to_send = my_fstbin;
|
||
nbins_to_send = my_nbins;
|
||
bytes_in_buff = 0;
|
||
nxt = (char *) my_pntr.base;
|
||
|
||
while (nbins_to_send > 0) {
|
||
/* Read some histogram data into buffer */
|
||
lastbin = nxtbin_to_send + bins_in_buff;
|
||
if(lastbin > my_nbins-1){
|
||
lastbin = my_nbins-1;
|
||
}
|
||
bins_to_go = FS_read_hm (index, pkt_size,
|
||
my_pntr.base, bins_in_buff,
|
||
nxtbin_to_send, lastbin);
|
||
if (bins_to_go <= 0) {
|
||
perror (StrJoin (buff, pkt_size,
|
||
FS_name[index], "/FS_do_read: FS_read_hm error"));
|
||
free (my_pntr.base);
|
||
if (my_daq_save == 0) FS_do_daq (index, DAQ__CLR, &my_rqst, &my_rply);
|
||
return False;
|
||
}
|
||
nxt = (char *) my_pntr.base;
|
||
bytes_in_buff = bins_to_go * FS_bpb;
|
||
while (bytes_in_buff > 0) { /* Send data to user */
|
||
bytes_to_go = (bytes_in_buff > pkt_size) ? pkt_size : bytes_in_buff;
|
||
is = send (rw_skt, nxt, bytes_to_go, 0);
|
||
if (is <= 0) {
|
||
perror (StrJoin (buff, pkt_size,
|
||
FS_name[index], "/FS_do_read: send error"));
|
||
free (my_pntr.base);
|
||
if (my_daq_save == 0) FS_do_daq (index, DAQ__CLR, &my_rqst, &my_rply);
|
||
return False;
|
||
}
|
||
FS_bytes_put += bytes_to_go;
|
||
bytes_in_buff -= bytes_to_go;
|
||
nxt += bytes_to_go;
|
||
}
|
||
nxtbin_to_send += bins_to_go;
|
||
nbins_to_send -= bins_to_go;
|
||
}
|
||
|
||
/*
|
||
** Read-out complete so let DAQ continue.
|
||
*/
|
||
if (my_daq_save == 0) FS_do_daq (index, DAQ__CLR, &my_rqst, &my_rply);
|
||
return True;
|
||
}
|
||
/*
|
||
**--------------------------------------------------------------------------
|
||
** FS_do_write: Preset a consecutive region of the Hist Mem. The
|
||
** number of bins to preset is 'nbins' starting with
|
||
** bin 'first'. The data for the bins is read from
|
||
** the client.
|
||
*/
|
||
int FS_do_write (
|
||
/* ===========
|
||
*/ int index,
|
||
struct req_buff_struct *req_bf,
|
||
struct rply_buff_struct *rply_bf,
|
||
int rw_skt,
|
||
int pkt_size,
|
||
int nbins,
|
||
int first,
|
||
int bytes_per_bin,
|
||
int hist_no) {
|
||
return True;
|
||
}
|
||
/*
|
||
**--------------------------------------------------------------------------
|
||
** FS_do_zero: Action routine for SQHM_ZERO command.
|
||
*
|
||
* This is only partially functional. The definition for SQHM_ZERO states
|
||
* that it is possible to zero only parts of the histogram. The version
|
||
* below just forwards a full zero request to all slaves and thus fits
|
||
* the bill for FOCUS. Probably for any other instrument as well.
|
||
*
|
||
* Mark Koennecke, November 2000
|
||
*/
|
||
int FS_do_zero (
|
||
/* ===========
|
||
*/ struct rply_buff_struct *reply,
|
||
int indx,
|
||
int nbins,
|
||
int first_bin,
|
||
int hist_no) {
|
||
|
||
int i, iret, all_ok = True;
|
||
struct req_buff_struct request;
|
||
|
||
/*
|
||
set up the request structure which zeros the whole histogram
|
||
*/
|
||
request.bigend = htonl(0x12345678);
|
||
request.cmnd = htonl(SQHM_ZERO);
|
||
request.u.zero.hist_no = htonl(-1);
|
||
request.u.zero.first_bin = htonl(-1);
|
||
request.u.zero.n_bins = htonl(-1);
|
||
|
||
/*
|
||
** Claim the sem to avoid race conditions with other threads
|
||
*/
|
||
if (FS_use_sem_tmo) {
|
||
iret = semTake (FS_sem_daq, FS_sem_tmo);
|
||
}else {
|
||
iret = semTake (FS_sem_daq, WAIT_FOREVER);
|
||
}
|
||
|
||
/*
|
||
send the request to all known slaves
|
||
*/
|
||
for (i = 0; i < FS_n_slaves; i++) {
|
||
if (FS_slv_active[i]) {
|
||
if (indx == 0) { /* If we are the master-server, send it to the
|
||
** master-servers in the slaves. */
|
||
iret = FS_send_cmnd_to_mstr (&FS_rmt_socknam[i],
|
||
&request, sizeof (request), reply,
|
||
&FS_bytes_got, &FS_bytes_put);
|
||
if (!iret || (ntohl (reply->status) != KER__SUCCESS)) all_ok=False;
|
||
}else {
|
||
iret = rqst_send_get (FS_skt[indx][i], &request, sizeof (request),
|
||
reply, sizeof (*reply),
|
||
&FS_bytes_got, &FS_bytes_put, FS_name[indx]);
|
||
if (!iret || (ntohl (reply->status) != KER__SUCCESS)) all_ok=False;
|
||
}
|
||
}
|
||
}
|
||
if (!all_ok) { /* If error, go no further! */
|
||
printf("Error zeroing histogram no %d\n", i);
|
||
semGive (FS_sem_daq);
|
||
return all_ok;
|
||
}
|
||
|
||
/*
|
||
tell the world about our success
|
||
*/
|
||
reply->status = htonl (KER__SUCCESS);
|
||
|
||
/* release semaphore */
|
||
semGive (FS_sem_daq);
|
||
|
||
|
||
return True;
|
||
}
|
||
/*
|
||
**--------------------------------------------------------------------------
|
||
** FS_free_memory: Free any memory allocated for FOCUS_srv
|
||
*/
|
||
void FS_free_memory (
|
||
/* ==============
|
||
*/ void *extras) {
|
||
|
||
int i;
|
||
/*
|
||
** Release a possible pending buffer
|
||
*/
|
||
free (extras);
|
||
/*
|
||
** Release any allocated histogram buffer
|
||
*/
|
||
free (FS_base_addr);
|
||
FS_base_addr = NULL;
|
||
}
|
||
/*
|
||
**--------------------------------------------------------------------------
|
||
** FS_kill_children: Send signals to all our offspring to cause
|
||
** them to terminate.
|
||
*/
|
||
void FS_kill_children (
|
||
/* ================
|
||
*/ int max_chld,
|
||
pid_t *pids,
|
||
char **tsk_names,
|
||
char *filler_name) {
|
||
|
||
int i, is;
|
||
|
||
if (pids[0] != 0) {
|
||
printf (" .. closing down %s ..", filler_name);
|
||
is = kill (pids[0], SIGINT);
|
||
if (!is) printf ("\nBad status killing %s.\n", filler_name);
|
||
}
|
||
for (i = 1; i <= max_chld; i++) {
|
||
if (pids[i] != 0) {
|
||
printf ("\n Terminating %s ..", tsk_names[i]);
|
||
is = kill (pids[i], SIGINT);
|
||
if (is == ERROR) printf ("\nBad status killing %s.\n", tsk_names[i]);
|
||
}
|
||
}
|
||
}
|
||
/*
|
||
**--------------------------------------------------------------------------
|
||
** FS_make_child: Find a free child index, create a child process and
|
||
** invoke procedure proc in the child procedure.
|
||
** Return value >= 0 if child successfully created;
|
||
** = -1 if error returned by fork;
|
||
** = -2 if there are too many children already;
|
||
** = -3 if time-out waiting for child to signal.
|
||
** < -3 the child indicated a start-up error. The
|
||
** child's error code is the return
|
||
** value + 3.
|
||
*/
|
||
int FS_make_child (
|
||
/* =============
|
||
*/ int (* proc) (), /* The procedure to be started */
|
||
int prty, /* The child's priority */
|
||
int spnd, /* "Suspend" flag to help debug the child */
|
||
int pkt_size, /* TCP/IP packet size to be used */
|
||
int max_chld, /* The size of the following arrays */
|
||
pid_t *pids, /* Array of PIDs of children */
|
||
int *exit_stat, /* Array of children's exit stati */
|
||
int *pcnt_SIGUSR1, /* Flag set on SIGUSR1 signals whenever
|
||
** a child exits. */
|
||
char *name) { /* Prefix for child's name */
|
||
|
||
int i, status, tmo;
|
||
pid_t created_pid;
|
||
char tsknam[20];
|
||
SEM_ID my_sem;
|
||
/*
|
||
** Find a free PID index. Zero is not a permitted value.
|
||
*/
|
||
for (i = 1; i <= max_chld; i++) if (pids[i] == 0) break;
|
||
|
||
if (i > max_chld) { /* Free index found? */
|
||
return -2; /* No, there are already too many children. */
|
||
}else {
|
||
if (pcnt_SIGUSR1 != NULL) *pcnt_SIGUSR1 = 0;
|
||
my_sem = semBCreate (SEM_Q_FIFO, SEM_EMPTY); /* Create a claimed sem-
|
||
** -aphore which the child can release when
|
||
** it has finished its initialisation. */
|
||
exit_stat[i] = 0; /* Zero child's status indicator */
|
||
sprintf (tsknam, "%.*s%02d", (sizeof (tsknam) - 3),
|
||
name, i); /* Generate the child's name */
|
||
created_pid = taskSpawn ( /* Make a child */
|
||
tsknam, /* Name */
|
||
prty, /* Priority */
|
||
VX_FP_TASK, /* Options - fl.pt. usage assumed */
|
||
20000, /* Stack size */
|
||
proc, /* The entry point */
|
||
FS_pid, (int) my_sem, i, pkt_size, spnd,
|
||
(int) &exit_stat[i],
|
||
0, 0, 0, 0);
|
||
if (created_pid == ERROR) { /* Error? */
|
||
return -1; /* Yes. */
|
||
}else { /* Parent */
|
||
pids[i] = created_pid;
|
||
tmo = 1000; /* Normally give child 1000 ticks to ..
|
||
** .. get going */
|
||
if (spnd != 0) {
|
||
tmo = WAIT_FOREVER; /* But in debug mode, wait forever! */
|
||
}
|
||
status = semTake (my_sem, tmo); /* Wait for child to get going */
|
||
semDelete (my_sem);
|
||
if (status == ERROR) { /* Timeout? */
|
||
taskDelete (pids[i]); /* Yes, kill child. */
|
||
pids[i] = 0;
|
||
return -3; /* Return with error. */
|
||
}else { /* No timeout so child is ready. */
|
||
if (exit_stat[i] >= 0) { /* Did the child have a startup ..
|
||
** .. problem */
|
||
return i; /* No, so return its index */
|
||
}else {
|
||
return (exit_stat[i] - 3); /* Yes, so return error */
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
/*
|
||
**--------------------------------------------------------------------------
|
||
** FS_project_hm: Project a block of histogram data.
|
||
**
|
||
** Return value = # of bins in buffer, each of size uint.
|
||
** Notes:
|
||
** This is an internal routine so all args are assumed to be OK.
|
||
*/
|
||
int FS_project_hm (
|
||
/* =============
|
||
*/ int index,
|
||
int pkt_size,
|
||
uint *buff, /* Buffer to receive the data */
|
||
uint *w_buff, /* Workspace */
|
||
uint blen_in_bins, /* Size of buff and w_buff in bins */
|
||
uint sub_code, /* 0 or PROJECT__ON_Y */
|
||
uint lo_cntr, /* First counter wanted */
|
||
uint hi_cntr, /* Last counter wanted */
|
||
uint fst_bin, /* First bin wanted */
|
||
uint lst_bin) { /* Last bin wanted */
|
||
|
||
int i, j, k, nx, ny, iret;
|
||
uint s_lo_cntr, s_hi_cntr, bytes_to_come;
|
||
uint f_cntr, l_cntr, n_cntr_got;
|
||
uint f_bin, l_bin, n_bins_got;
|
||
uchar *b_pntr;
|
||
struct req_buff_struct my_rq;
|
||
struct rply_buff_struct my_rp;
|
||
/*
|
||
** There are 2 cases: project on x and project on y.
|
||
** Project on x is expected to be the more common!
|
||
*/
|
||
if (sub_code != PROJECT__ON_Y) {
|
||
n_cntr_got = 0; /* Project on X */
|
||
memset (buff, 0, (blen_in_bins * sizeof (uint))); /* Zero the buffer */
|
||
for (i = 0; i < FS_n_slaves; i++) { /* Find which slave(s) has the wanted data */
|
||
s_lo_cntr = FS_lo_det[i];
|
||
s_hi_cntr = FS_hi_det[i];
|
||
if (((s_lo_cntr >= lo_cntr) && (s_hi_cntr <= hi_cntr)) ||
|
||
((s_lo_cntr < lo_cntr) && (s_hi_cntr > hi_cntr)) ||
|
||
((s_lo_cntr < lo_cntr) && (s_hi_cntr >= lo_cntr)) ||
|
||
((s_lo_cntr <= hi_cntr) && (s_hi_cntr > hi_cntr))) {
|
||
f_cntr = (s_lo_cntr >= lo_cntr) ? 0 : (lo_cntr - s_lo_cntr);
|
||
l_cntr = (s_hi_cntr <= hi_cntr) ? (s_hi_cntr - s_lo_cntr) :
|
||
(hi_cntr - s_lo_cntr);
|
||
my_rq.bigend = htonl (0x12345678);
|
||
my_rq.cmnd = htonl (SQHM_PROJECT);
|
||
my_rq.u.project.sub_code = htonl (0);
|
||
my_rq.u.project.x_lo = htonl (fst_bin);
|
||
my_rq.u.project.nx = htonl (lst_bin - fst_bin + 1);
|
||
my_rq.u.project.y_lo = htonl (f_cntr);
|
||
my_rq.u.project.ny = htonl (l_cntr - f_cntr + 1);
|
||
my_rq.u.project.xdim = htonl (0);
|
||
my_rq.u.project.nhist = htonl (0);
|
||
iret = rqst_send_get (FS_skt[index][i], &my_rq, sizeof (my_rq),
|
||
&my_rp, sizeof (my_rp),
|
||
&FS_bytes_put, &FS_bytes_got, FS_name[index]);
|
||
if (!iret) {return 0;};
|
||
if (ntohl (my_rp.status) != KER__SUCCESS) {return 0;};
|
||
nx = ntohl (my_rp.u.project.n_bins); /* # of bins to be read */
|
||
bytes_to_come = nx * ntohl (my_rp.u.project.bytes_per_bin);
|
||
b_pntr = (uchar *) w_buff;
|
||
while (bytes_to_come > 0) {
|
||
j = (bytes_to_come > pkt_size) ? pkt_size : bytes_to_come;
|
||
k = recv (FS_skt[index][i], b_pntr, j, 0);
|
||
if (k <= 0) {perror ("FS_project_hm"); return 0;}
|
||
bytes_to_come -= k;
|
||
b_pntr += k;
|
||
}
|
||
k = l_cntr - f_cntr + 1;
|
||
n_cntr_got += k;
|
||
lo_cntr += k;
|
||
for (k = 0; k < nx; k++) buff[k] += ntohl (w_buff[k]);
|
||
}
|
||
}
|
||
return nx;
|
||
}else {
|
||
n_cntr_got = 0; /* Project on Y */
|
||
for (i = 0; i < 3; i++) { /* Find which slave(s) has the wanted data */
|
||
s_lo_cntr = FS_lo_det[i];
|
||
s_hi_cntr = FS_hi_det[i];
|
||
if (((s_lo_cntr >= lo_cntr) && (s_hi_cntr <= hi_cntr)) ||
|
||
((s_lo_cntr < lo_cntr) && (s_hi_cntr > hi_cntr)) ||
|
||
((s_lo_cntr < lo_cntr) && (s_hi_cntr >= lo_cntr)) ||
|
||
((s_lo_cntr <= hi_cntr) && (s_hi_cntr > hi_cntr))) {
|
||
f_cntr = (s_lo_cntr >= lo_cntr) ? 0 : (lo_cntr - s_lo_cntr);
|
||
l_cntr = (s_hi_cntr <= hi_cntr) ? (s_hi_cntr - s_lo_cntr) :
|
||
(hi_cntr - s_lo_cntr);
|
||
my_rq.bigend = htonl (0x12345678);
|
||
my_rq.cmnd = htonl (SQHM_PROJECT);
|
||
my_rq.u.project.sub_code = htonl (PROJECT__ON_Y);
|
||
my_rq.u.project.x_lo = htonl (fst_bin);
|
||
my_rq.u.project.nx = htonl (lst_bin - fst_bin + 1);
|
||
my_rq.u.project.y_lo = htonl (f_cntr);
|
||
my_rq.u.project.ny = htonl (l_cntr - f_cntr + 1);
|
||
my_rq.u.project.xdim = htonl (0);
|
||
my_rq.u.project.nhist = htonl (0);
|
||
iret = rqst_send_get (FS_skt[index][i], &my_rq, sizeof (my_rq),
|
||
&my_rp, sizeof (my_rp),
|
||
&FS_bytes_put, &FS_bytes_got, FS_name[index]);
|
||
if (!iret) {return 0;};
|
||
if (ntohl (my_rp.status) != KER__SUCCESS) {return 0;};
|
||
ny = ntohl (my_rp.u.project.n_bins); /* # of elements to be read */
|
||
bytes_to_come = ny * ntohl (my_rp.u.project.bytes_per_bin);
|
||
b_pntr = (uchar *) w_buff;
|
||
while (bytes_to_come > 0) {
|
||
j = (bytes_to_come > pkt_size) ? pkt_size : bytes_to_come;
|
||
k = recv (FS_skt[index][i], b_pntr, j, 0);
|
||
if (k <= 0) {perror ("FS_project_hm"); return 0;}
|
||
bytes_to_come -= k;
|
||
b_pntr += k;
|
||
}
|
||
for (k = 0; k < ny; k++) buff[n_cntr_got+k] = ntohl (w_buff[k]);
|
||
n_cntr_got += ny;
|
||
lo_cntr += ny;
|
||
}
|
||
}
|
||
return n_cntr_got;
|
||
}
|
||
}
|
||
/*
|
||
**--------------------------------------------------------------------------
|
||
** FS_read_hm: Read a block of histogram data.
|
||
**
|
||
** Return value = # of bins read.
|
||
*/
|
||
int FS_read_hm (
|
||
/* ==========
|
||
*/ int index,
|
||
int pkt_size,
|
||
uchar *buff, /* Buffer to receive the data */
|
||
uint blen_in_bins, /* Size of buff in bins */
|
||
uint fst_bin, /* First bin wanted */
|
||
uint lst_bin) { /* Last bin wanted */
|
||
|
||
int i, j, k, iret;
|
||
uint s_fst_bin, s_lst_bin, bins_per_hist;
|
||
uint f_bin, l_bin, bytes_to_come, n_bins_got;
|
||
struct req_buff_struct my_rq;
|
||
struct rply_buff_struct my_rp;
|
||
|
||
bins_per_hist = FS_hi_bin - FS_lo_bin + 1;
|
||
n_bins_got = 0;
|
||
|
||
for (i = 0; i < 3; i++) { /* Find which slave(s) has the wanted data */
|
||
s_fst_bin = 0;
|
||
for (j = 0; j < i; j++) {
|
||
s_fst_bin += (FS_hi_det[j] - FS_lo_det[j] + 1) * bins_per_hist;
|
||
}
|
||
s_lst_bin = s_fst_bin +
|
||
(FS_hi_det[i] - FS_lo_det[i] + 1) * bins_per_hist - 1;
|
||
if (((s_fst_bin >= fst_bin) && (s_lst_bin <= lst_bin)) ||
|
||
((s_fst_bin < fst_bin) && (s_lst_bin > lst_bin)) ||
|
||
((s_fst_bin < fst_bin) && (s_lst_bin >= fst_bin)) ||
|
||
((s_fst_bin <= lst_bin) && (s_lst_bin > lst_bin))) {
|
||
f_bin = (s_fst_bin >= fst_bin) ? 0 : (fst_bin - s_fst_bin);
|
||
l_bin = (s_lst_bin <= lst_bin) ? (s_lst_bin - s_fst_bin) :
|
||
(lst_bin - s_fst_bin);
|
||
my_rq.bigend = htonl (0x12345678);
|
||
my_rq.cmnd = htonl (SQHM_READ);
|
||
my_rq.u.read.hist_no = htonl (-1);
|
||
my_rq.u.read.first_bin = htonl (f_bin);
|
||
my_rq.u.read.n_bins = htonl (l_bin - f_bin + 1);
|
||
iret = rqst_send_get (FS_skt[index][i], &my_rq, sizeof (my_rq),
|
||
&my_rp, sizeof (my_rp),
|
||
&FS_bytes_put, &FS_bytes_got, FS_name[index]);
|
||
if (!iret) {return 0;};
|
||
if (ntohl (my_rp.status) != KER__SUCCESS) {return 0;};
|
||
k = ntohl (my_rp.u.read.n_bins); /* # of bins to be read */
|
||
bytes_to_come = k * FS_bpb;
|
||
while (bytes_to_come > 0) {
|
||
j = (bytes_to_come > pkt_size) ? pkt_size : bytes_to_come;
|
||
k = recv (FS_skt[index][i], buff, j, 0);
|
||
if (k <= 0) {perror ("FS_read_hm"); return 0;}
|
||
bytes_to_come -= k;
|
||
buff += k;
|
||
}
|
||
k = l_bin - f_bin + 1;
|
||
n_bins_got += k;
|
||
fst_bin += k;
|
||
}
|
||
}
|
||
return n_bins_got;
|
||
}
|
||
/*
|
||
**--------------------------------------------------------------------------*/
|
||
int FS_rply_status_send (
|
||
/* ===================
|
||
*/ int skt,
|
||
struct rply_buff_struct *rply_bf,
|
||
uint *cntr_out) {
|
||
|
||
int is;
|
||
|
||
is = send (skt, (char *) rply_bf, sizeof (*rply_bf), 0);
|
||
if (is == sizeof (*rply_bf)) {
|
||
*cntr_out += is;
|
||
return True;
|
||
}else {
|
||
return False;
|
||
}
|
||
}
|
||
/*
|
||
**--------------------------------------------------------------------------*/
|
||
int FS_rply_status_setup_and_send (
|
||
/* =============================
|
||
*/ int skt,
|
||
struct rply_buff_struct *rply_bf,
|
||
int status,
|
||
int sub_status,
|
||
char *msg,
|
||
uint *cntr_out) {
|
||
|
||
int is;
|
||
|
||
rply_status_setup (rply_bf, status, sub_status, msg);
|
||
is = FS_rply_status_send (skt, rply_bf, cntr_out);
|
||
|
||
return is;
|
||
}
|
||
/*
|
||
**--------------------------------------------------------------------------
|
||
** FS_send_cmnd_to_mstr: Send command to Sinqm-Master process
|
||
** in a slave.
|
||
*/
|
||
int FS_send_cmnd_to_mstr (
|
||
/* ====================
|
||
*/ struct sockaddr_in *rmt_sockname,
|
||
struct req_buff_struct *request,
|
||
int requ_len,
|
||
struct rply_buff_struct *reply,
|
||
uint *in_cntr,
|
||
uint *out_cntr) {
|
||
|
||
int status, cnct_skt, rmt_sockname_len, i;
|
||
int bytes_to_come, nbytes;
|
||
char *p_nxt_byte;
|
||
struct sockaddr_in lcl_sockname;
|
||
/*
|
||
** Create a TCP/IP socket for connecting to SINQHM_SRV root and bind it.
|
||
*/
|
||
cnct_skt = socket (AF_INET, SOCK_STREAM, 0);
|
||
i = 1;
|
||
setsockopt(cnct_skt,SOL_SOCKET, SO_REUSEADDR, &i,sizeof(int));
|
||
if (cnct_skt == -1) {
|
||
close(cnct_skt);
|
||
failInet ("\nFS_send_cmnd_to_mstr: socket error.");
|
||
}
|
||
|
||
setup_host (NULL, &lcl_sockname, 0, False);
|
||
status = bind (cnct_skt, (struct sockaddr *) &lcl_sockname,
|
||
sizeof (lcl_sockname));
|
||
if (status == -1){
|
||
close(cnct_skt);
|
||
failInet ("\nFS_send_cmnd_to_mstr: bind error.");
|
||
}
|
||
/*
|
||
** Connect to SINQHM_SRV root.
|
||
*/
|
||
rmt_sockname_len = sizeof (*rmt_sockname);
|
||
status = connect (cnct_skt, (struct sockaddr *) rmt_sockname,
|
||
rmt_sockname_len);
|
||
if (status == -1) {
|
||
close(cnct_skt);
|
||
getErrno (&FS_errno);
|
||
failInet ("\nFS_send_cmnd_to_mstr: connect error");
|
||
}
|
||
/*
|
||
** Send the request to the server
|
||
*/
|
||
status = send (cnct_skt, (char *) request, requ_len, 0);
|
||
if (status == -1) {
|
||
close(cnct_skt);
|
||
failInet ("\nFS_send_cmnd_to_mstr -- send error");
|
||
}
|
||
if (status != requ_len) {
|
||
printf ("\nFS_send_cmnd_to_mstr -- wrong number of bytes sent: %d %d\n",
|
||
status, requ_len);
|
||
close(cnct_skt);
|
||
return False;
|
||
}
|
||
*out_cntr += requ_len;
|
||
/*
|
||
** Wait for the status response.
|
||
*/
|
||
bytes_to_come = sizeof (*reply);
|
||
p_nxt_byte = (char *) reply;
|
||
while (bytes_to_come > 0) {
|
||
nbytes = recv (cnct_skt, p_nxt_byte, bytes_to_come, 0);
|
||
if (nbytes <= 0) break;
|
||
*in_cntr += nbytes;
|
||
bytes_to_come -= nbytes;
|
||
p_nxt_byte += nbytes;
|
||
}
|
||
if (nbytes == -1) {
|
||
close(cnct_skt);
|
||
failInet ("\nFS_send_cmnd_to_mstr -- recv error");
|
||
return False;
|
||
}else if (nbytes == 0) {
|
||
printf ("\nFS_send_cmnd_to_mstr -- server has closed connection!\n");
|
||
close(cnct_skt);
|
||
return False;
|
||
}else if (ntohl (reply->bigend) != 0x12345678) {
|
||
/* Network byte-order wrong! */
|
||
printf ("\nFS_send_cmnd_to_mstr -- big-endian/little-endian problem!\n"
|
||
" Buffer received in non-network byte order!\n");
|
||
close(cnct_skt);
|
||
return False;
|
||
}
|
||
close(cnct_skt);
|
||
return True;
|
||
}
|
||
/*
|
||
**--------------------------------------------------------------------------
|
||
** rqst_send_get: Send a network request and get reply
|
||
*/
|
||
int rqst_send_get (
|
||
/* =============
|
||
*/ int skt,
|
||
struct req_buff_struct *rqst_bf,
|
||
int rq_len,
|
||
struct rply_buff_struct *rply_bf,
|
||
int rp_size,
|
||
int *out_cntr,
|
||
int *in_cntr,
|
||
char *tsk_name) {
|
||
|
||
int status, bytes_to_come, nbytes, n_bytes_got;
|
||
char recd[80], *p_addr;
|
||
/*
|
||
** Send the request to the server
|
||
*/
|
||
status = send (skt, (char *) rqst_bf, rq_len, 0);
|
||
if (status == -1) {
|
||
perror (StrJoin (recd, sizeof (recd),
|
||
tsk_name, "/rqst_send_get: send error"));
|
||
return False;
|
||
}
|
||
if (status != rq_len) {
|
||
printf ("\n%s/rqst_send_get: wrong number of bytes sent: %d %d\n",
|
||
tsk_name, status, rq_len);
|
||
return False;
|
||
}
|
||
*out_cntr += rq_len;
|
||
/*
|
||
** Wait for the response.
|
||
*/
|
||
bytes_to_come = rp_size;
|
||
p_addr = (char *) rply_bf;
|
||
while (bytes_to_come > 0) {
|
||
n_bytes_got = recv (skt, p_addr, bytes_to_come, 0);
|
||
if (n_bytes_got <= 0) break;
|
||
*in_cntr += n_bytes_got;
|
||
bytes_to_come -= n_bytes_got;
|
||
p_addr += n_bytes_got;
|
||
}
|
||
if (n_bytes_got < 0) {
|
||
perror (StrJoin (recd, sizeof (recd),
|
||
tsk_name, "/rqst_send_get: recv error"));
|
||
return False;
|
||
}else if (n_bytes_got == 0) {
|
||
printf ("\n%s/rqst_send_get: zero bytes received!\n", tsk_name);
|
||
return False;
|
||
}else if (ntohl (rply_bf->bigend) != 0x12345678) {
|
||
printf ("\n%s/rqst_send_get: big-endian/little-endian problem!\n",
|
||
tsk_name);
|
||
return False;
|
||
}
|
||
return True;
|
||
}
|
||
/*
|
||
**--------------------------------------------------------------------------
|
||
** setup_host: Setup Internet structures for a named host
|
||
*/
|
||
int setup_host (
|
||
/* ==========
|
||
*/ char *host,
|
||
struct sockaddr_in *sockname,
|
||
int port,
|
||
int verbose) {
|
||
|
||
int i, j, k, l, m;
|
||
char my_host[64], my_addr[32];
|
||
struct in_addr my_inet_addr;
|
||
|
||
if (host == NULL) {
|
||
my_inet_addr.s_addr = 0;
|
||
}else {
|
||
if (strlen (host) >= sizeof (my_host)) return False;
|
||
for (i = 0; i <= strlen (host); i++) my_host[i] = tolower (host[i]);
|
||
/*
|
||
** Try to convert the Internet address. First assume it is dot
|
||
** notation. If this fails, see if we can recognise the name.
|
||
*/
|
||
my_inet_addr.s_addr = inet_addr (my_host);
|
||
if (my_inet_addr.s_addr == ERROR) {
|
||
if (strcmp (my_host, "localhost") == 0) {
|
||
my_inet_addr.s_addr = inet_addr ("127.0.0.1");
|
||
}else {
|
||
i = sscanf (my_host, "lnse%d%n", &j, &k);
|
||
if ((i == 1) && (k == 6)) {
|
||
if (strcmp (&my_host[k], ".vme") == 0) {
|
||
sprintf (my_addr, "192.168.11.%d", j); /* "lnse??.vme" */
|
||
}else {
|
||
sprintf (my_addr, "129.129.62.%d", (100+j)); /* "lnse??" */
|
||
}
|
||
my_inet_addr.s_addr = inet_addr (my_addr);
|
||
}else {
|
||
i = sscanf (my_host, "psds%d%n", &j, &k);
|
||
if ((i == 1) && (k == 6) && (my_host[k] == NIL)) {
|
||
sprintf (my_addr, "129.129.62.%d", j); /* "psds??" */
|
||
my_inet_addr.s_addr = inet_addr (my_addr);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
if (my_inet_addr.s_addr == ERROR) {
|
||
printf ("\nsetup_host: Node \"%s\" is unknown.\n", host);
|
||
return False;
|
||
}
|
||
if (verbose) {
|
||
printf ("Host is %s ", host);
|
||
inet_ntoa_b (my_inet_addr, my_addr);
|
||
printf ("(%s),", my_addr);
|
||
printf (" Port %d.\n", port);
|
||
}
|
||
sockname->sin_family = AF_INET;
|
||
sockname->sin_port = htons (port);
|
||
sockname->sin_addr.s_addr = my_inet_addr.s_addr;
|
||
}
|
||
/*
|
||
**--------------------------------------------------------------------------
|
||
** socket_bind: Setup an Internet socket and bind it to a port.
|
||
*/
|
||
int socket_bind (
|
||
/* ===========
|
||
*/ int port,
|
||
char *tsk_name) {
|
||
|
||
int status, skt;
|
||
struct sockaddr_in sockname;
|
||
char recd[80];
|
||
|
||
skt = socket (AF_INET, SOCK_STREAM, 0);
|
||
if (skt == -1) {
|
||
perror (StrJoin (recd, sizeof (recd), tsk_name,
|
||
" -- socket error in socket_bind"));
|
||
return skt;
|
||
}
|
||
status = 1;
|
||
setsockopt(skt,SOL_SOCKET, SO_REUSEADDR, &status, sizeof(int));
|
||
|
||
setup_host (NULL, &sockname, port, False);
|
||
status = bind (skt, (struct sockaddr *) &sockname, sizeof (sockname));
|
||
if (status != 0) {
|
||
close (skt);
|
||
perror (StrJoin (recd, sizeof (recd), tsk_name,
|
||
" -- bind error in socket_bind"));
|
||
return -1;
|
||
}
|
||
return skt;
|
||
}
|
||
/*
|
||
**==============================================================================
|
||
** Main line program
|
||
** ------------------
|
||
**============================================================================*/
|
||
int FOCUS_main (
|
||
/* ==========
|
||
*/ char *hostM, int ndetM,
|
||
char *hostO, int ndetO,
|
||
char *hostU, int ndetU,
|
||
int c_port, /* Our port # as client */
|
||
int s_port, /* Our port # for serving */
|
||
int arg9, int suspend) {
|
||
/*============================================================================*/
|
||
struct req_buff_struct req_buff;
|
||
struct rply_buff_struct rply_buff;
|
||
|
||
int i, j, is, status, cntr;
|
||
int keep_going = True;
|
||
int bytes_to_come, n_bytes_got;
|
||
char *p_addr;
|
||
int cl_port;
|
||
struct sockaddr_in lcl_sockname;
|
||
struct sockaddr_in rmt_sockname;
|
||
int rmt_sockname_len;
|
||
int pkt_size;
|
||
time_t timer;
|
||
char buff[132];
|
||
|
||
sigset_t proc_sigmask;
|
||
struct sigaction sig_action;
|
||
|
||
/*============================================================================
|
||
*/
|
||
printf ("\n");
|
||
printf ("hostM = \"%s\" %d cntrs\n", hostM, ndetM);
|
||
printf ("hostO = \"%s\" %d cntrs\n", hostO, ndetO);
|
||
printf ("hostU = \"%s\" %d cntrs\n", hostU, ndetU);
|
||
printf ("Client port = %d\n", c_port);
|
||
printf ("Server port = %d\n", s_port);
|
||
|
||
if (suspend != 0) {
|
||
printf ("\nFOCUS_srv: Suspending ...\n");
|
||
taskSuspend (0); /* We've been told to suspend ourself, ..
|
||
** .. presumably for debug reasons.
|
||
*/
|
||
printf ("\nFOCUS_srv: Suspension ended!\n");
|
||
}
|
||
/*============================================================================
|
||
** Perform the initialisation of global variables ...
|
||
*/
|
||
StrJoin (FS_inst, sizeof (FS_inst), INST, ""); /* Save the instr.
|
||
** name in a global
|
||
*/
|
||
StrJoin (FS_def_ident, sizeof (FS_def_ident), SINQHM_DEF_ID, "");
|
||
StrJoin (FS_main_ident, sizeof (FS_main_ident), IDENT, "");
|
||
StrJoin (FS_main_date, sizeof (FS_main_date), __DATE__, ", ");
|
||
StrJoin (FS_main_date, sizeof (FS_main_date), FS_main_date, __TIME__);
|
||
time (&FS_start_time); /* Initialise the start time */
|
||
FS_serv_ident[0] = NIL;
|
||
FS_serv_date[0] = NIL;
|
||
FS_rout_ident[0] = NIL;
|
||
FS_rout_date[0] = NIL;
|
||
|
||
FS_cfgn_done = False; /* Force a configuration before we can do anything. */
|
||
|
||
FS_bytes_got = 0; FS_bytes_put = 0;
|
||
FS_dbg_mask = FS_dbg_lev0 = FS_dbg_lev1 = FS_dbg_lev2 = FS_dbg_lev3 = 0;
|
||
|
||
FS_free_memory (NULL); /* Release memory (possibly) in case ..
|
||
** .. of a restart of the program */
|
||
if (FS_cnct_skt != 0) close (FS_cnct_skt);
|
||
if (FS_rw_skt != 0) close (FS_rw_skt);
|
||
FS_cnct_skt = FS_rw_skt = 0;
|
||
|
||
for (i = 0; i <= MAX_CLIENTS; i++) {
|
||
FS_pids[i] = 0;
|
||
FS_chld_exit_status[i] = 0;
|
||
if (FS_chld_cnct_skt[i] != 0) close (FS_chld_cnct_skt[i]);
|
||
if (FS_chld_rw_skt[i] != 0) close (FS_chld_rw_skt[i]);
|
||
FS_chld_cnct_skt[i] = FS_chld_rw_skt[i] = 0;
|
||
FS_p_names[i] = &FS_name[i][0]; FS_name[i][0] = NIL;
|
||
for (j = 0; j < MAX_SLV; j++) {
|
||
if (FS_skt[i][j] != 0) {close (FS_skt[i][j]); FS_skt[i][j] = 0;}
|
||
}
|
||
FS_srv_masks[i] = (i == 0) ? 0x8000 : 1 << (i - 1);
|
||
}
|
||
|
||
if (FS_sem_daq == NULL) {
|
||
FS_sem_daq = semBCreate (SEM_Q_FIFO, SEM_FULL); /* Create a released sem-
|
||
** aphore for guarding access to
|
||
** FS_dsbl_mask */
|
||
}
|
||
FS_dsbl_mask = 0; /* Start up with DAQ enabled */
|
||
|
||
FS_pid = get_pid (); /* Store our pid */
|
||
StrJoin (FS_name[0], sizeof (FS_name[0]), /* And our task name */
|
||
taskName (FS_pid), "");
|
||
/*
|
||
** Debug hint - set FS_use_sem_tmo to False (== 0) to disable sem time-outs
|
||
** during debug sessions. This will stop things falling off.
|
||
*/
|
||
FS_sem_tmo = 5 * sysClkRateGet (); /* 5 second time-out by default */
|
||
FS_use_sem_tmo = True;
|
||
/*
|
||
** Do all the necessary network orientated setup for our slaves to
|
||
** make it easier to broadcast commands to them.
|
||
*/
|
||
/*
|
||
** Get Internet address of the front-end.
|
||
*/
|
||
FS_n_slaves = 3;
|
||
if ((c_port < 128) || (c_port > 32767)) c_port = 2500;
|
||
|
||
status = setup_host (hostM, &FS_rmt_socknam[0], c_port, True);
|
||
if (status) FS_slaves[0] = hostM; else FS_slaves[0] = NULL;
|
||
status = setup_host (hostO, &FS_rmt_socknam[1], c_port, True);
|
||
if (status) FS_slaves[1] = hostO; else FS_slaves[1] = NULL;
|
||
status = setup_host (hostU, &FS_rmt_socknam[2], c_port, True);
|
||
if (status) FS_slaves[2] = hostU; else FS_slaves[2] = NULL;
|
||
|
||
FS_lo_det[0] = 0;
|
||
FS_hi_det[0] = FS_lo_det[0] + ndetM - 1;
|
||
FS_lo_det[1] = FS_hi_det[0] + 1;
|
||
FS_hi_det[1] = FS_lo_det[1] + ndetO - 1;
|
||
FS_lo_det[2] = FS_hi_det[1] + 1;
|
||
FS_hi_det[2] = FS_lo_det[2] + ndetU - 1;
|
||
if (ndetM == 0) FS_slaves[0] = NULL;
|
||
if (ndetO == 0) FS_slaves[1] = NULL;
|
||
if (ndetU == 0) FS_slaves[2] = NULL;
|
||
|
||
for (i = 0; i <= FS_n_slaves; i++) {
|
||
FS_slv_active[i] = False;
|
||
}
|
||
/*============================================================================
|
||
** Clear the process signal mask to let in all signals (actually, on
|
||
** PPC VxWorks this seems to cause all signals to get ignored!) and then
|
||
** declare action routine for SIGUSR1. Our children signal with SIGUSR1
|
||
** just before they exit in a more or less controlled manner. If the
|
||
** child gets deleted from the shell, it will not signal.
|
||
*/
|
||
FS_cnt_SIGUSR1 = 0;
|
||
|
||
status = sigemptyset (&proc_sigmask);
|
||
status = sigprocmask (SIG_SETMASK, &proc_sigmask, NULL);
|
||
status = sigemptyset (&sig_action.sa_mask);
|
||
sig_action.sa_handler = FS_catch_signal;
|
||
sig_action.sa_flags = 0;
|
||
|
||
if (sigaction (SIGUSR1, &sig_action, NULL) == -1) {
|
||
getErrno (&FS_errno);
|
||
perror ("sigaction error:");
|
||
exit (0);
|
||
}
|
||
/*============================================================================
|
||
** Get a port number to use. If the argument "port" is not
|
||
** a valid port number (not in range 128 to 32767), use PORT_BASE.
|
||
*/
|
||
FS_port = PORT_BASE;
|
||
if ((s_port >= 128) && (s_port < 32768)) FS_port = s_port;
|
||
/*============================================================================
|
||
** Create a TCP/IP socket for receiving connection requests, bind it and
|
||
** set it to listen.
|
||
*/
|
||
FS_cnct_skt = socket (AF_INET, SOCK_STREAM, 0);
|
||
if (FS_cnct_skt == -1) {
|
||
sprintf (buff, "\n%s -- Cnct-Socket socket error", FS_name[0]);
|
||
failInet (buff);
|
||
}
|
||
status = 1;
|
||
setsockopt(FS_cnct_skt, SOL_SOCKET, SO_REUSEADDR, &status, sizeof(int));
|
||
setup_host (NULL, &lcl_sockname, FS_port, False);
|
||
status = bind (FS_cnct_skt, (struct sockaddr *) &lcl_sockname,
|
||
sizeof (lcl_sockname));
|
||
if (status != 0) {
|
||
sprintf (buff, "\n%s -- Cnct-Socket bind error", FS_name[0]);
|
||
failInet (buff);
|
||
}
|
||
status = listen (FS_cnct_skt, 5);
|
||
if (status != 0) {
|
||
sprintf (buff, "\n%s -- Cnct-Socket listen error", FS_name[0]);
|
||
failInet (buff);
|
||
}
|
||
/*
|
||
** Clients must now connect to the Connect-port and send either a
|
||
** connect, configure, deconfigure, status or exit request. A
|
||
** successful configure request must precede any connection request.
|
||
**
|
||
** When a configure request arrives, the histogram data structures are
|
||
** initialised, the histogram filler process (FILLER) is spawned and
|
||
** connection requests are enabled. A status reply is sent to the
|
||
** client and the connection closed.
|
||
**
|
||
** When a connection request arrives, a child will be spawned to
|
||
** handle the connection. The child will be told which port to use
|
||
** and he will release a semaphore when the port is ready. The parent
|
||
** then sends the client a reply to tell him which port to use. The
|
||
** connection is then closed to await further connections.
|
||
*/
|
||
setup_inet_info (FS_host, sizeof (FS_host), /* Find out who we are */
|
||
FS_addr, sizeof (FS_addr));
|
||
printf ("\n%s: Program Ident = \"%s\". Started on %s (%s).\n",
|
||
FS_name[0], IDENT, FS_host, FS_addr);
|
||
printf ("%s: Protocol Ident = \"%s\"\n", FS_name[0], FS_def_ident);
|
||
|
||
#ifndef INST
|
||
#error Define the target instrument via the symbol "INST"!
|
||
#endif
|
||
|
||
if (strcmp (INST, "FOCUS") == 0) {
|
||
printf ("%s: Instrument = \"%s\"\n", FS_name[0], "FOCUS");
|
||
}else {
|
||
printf ("%s: Instrument is not defined\n", FS_name[0]);
|
||
}
|
||
/*============================================================================*/
|
||
while (keep_going) {
|
||
rmt_sockname_len = sizeof (rmt_sockname);
|
||
FS_rw_skt = accept (FS_cnct_skt, (struct sockaddr *) &rmt_sockname,
|
||
&rmt_sockname_len);
|
||
if (FS_rw_skt == -1) {
|
||
getErrno (&FS_errno);
|
||
sprintf (buff, "\n%s -- Cnct-Socket accept error", FS_name[0]);
|
||
failInet (buff); /* No return */
|
||
}
|
||
|
||
p_addr = inet_ntoa (rmt_sockname.sin_addr);
|
||
cl_port = ntohs (rmt_sockname.sin_port);
|
||
printf ("\n%s: Connected to Node %s, Port %d.\n",
|
||
FS_name[0], p_addr, cl_port);
|
||
|
||
bytes_to_come = sizeof (req_buff); /* Read a command */
|
||
p_addr = (char *) &req_buff;
|
||
while (bytes_to_come > 0) {
|
||
n_bytes_got = recv (FS_rw_skt, p_addr, bytes_to_come, 0);
|
||
if (n_bytes_got <= 0) break;
|
||
FS_bytes_got += n_bytes_got;
|
||
bytes_to_come -= n_bytes_got;
|
||
p_addr += n_bytes_got;
|
||
}
|
||
|
||
if (FS_cnt_SIGUSR1 > 0) { /* Have any children exited? */
|
||
if (FS_dbg_lev0) printf ("\n%s: Cleaning up children ...", FS_name[0]);
|
||
FS_cleanup_children (MAX_CLIENTS, /* Yes, update our database. */
|
||
FS_pids, &FS_cnt_SIGUSR1, FS_dbg_lev0, FS_p_names, "");
|
||
if (FS_dbg_lev0) printf ("\n ... cleanup of children done.\n");
|
||
}
|
||
|
||
if (n_bytes_got < 0) {
|
||
printf ("\n%s -- R/W-Socket recv error\n", FS_name[0]);
|
||
printf ("%s -- Connection to %s will be closed.\n", FS_name[0],
|
||
inet_ntoa (rmt_sockname.sin_addr));
|
||
}else if (n_bytes_got == 0) {
|
||
printf ("\n%s -- no command received!\n", FS_name[0]);
|
||
printf ("%s -- Connection to %s will be closed.\n", FS_name[0],
|
||
inet_ntoa (rmt_sockname.sin_addr));
|
||
}else if (bytes_to_come != 0) {
|
||
printf ("\n%s -- command packet has wrong number of bytes:"
|
||
" %d instead of %d\n", FS_name[0],
|
||
n_bytes_got, sizeof (req_buff));
|
||
printf ("%s -- Connection to %s will be closed.\n", FS_name[0],
|
||
inet_ntoa (rmt_sockname.sin_addr));
|
||
}else if (ntohl (req_buff.bigend) != 0x12345678) {
|
||
printf ("\n%s -- big-endian/little-endian problem!\n"
|
||
" Buffer received in non-network byte order!\n", FS_name[0]);
|
||
}else {
|
||
FS_do_command (0, FS_rw_skt, 4096, &req_buff, &rply_buff);
|
||
}
|
||
close (FS_rw_skt); FS_rw_skt = 0;
|
||
if (ntohl (req_buff.cmnd) == SQHM_EXIT) keep_going = False;
|
||
}
|
||
/*============================================================================*/
|
||
close (FS_cnct_skt); FS_cnct_skt = 0;
|
||
exit (KER__SUCCESS);
|
||
}
|
||
/*========================================= End of FOCUS_srv_main.c ========*/
|