- added 150 detectors the default for FOCUS middle bank. - added documentation for el734_test
1588 lines
44 KiB
C
1588 lines
44 KiB
C
/*-------------------------------------------------------------------------
|
|
S I N Q H M
|
|
|
|
Implementation file for the SINQ histogram memory utility functions.
|
|
|
|
David Maden, Mark Koennecke, April 1997
|
|
|
|
Updated for TOF support: Mark Koennecke, December 1998
|
|
|
|
Copyright:
|
|
|
|
Labor fuer Neutronenstreuung
|
|
Paul Scherrer Institut
|
|
CH-5423 Villigen-PSI
|
|
|
|
|
|
The authors hereby grant permission to use, copy, modify, distribute,
|
|
and license this software and its documentation for any purpose, provided
|
|
that existing copyright notices are retained in all copies and that this
|
|
notice is included verbatim in any distributions. No written agreement,
|
|
license, or royalty fee is required for any of the authorized uses.
|
|
Modifications to this software may be copyrighted by their authors
|
|
and need not follow the licensing terms described here, provided that
|
|
the new terms are clearly indicated on the first page of each file where
|
|
they apply.
|
|
|
|
IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
|
|
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
|
ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
|
|
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
|
|
POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
|
|
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
|
|
FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE
|
|
IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE
|
|
NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
|
|
MODIFICATIONS.
|
|
----------------------------------------------------------------------------*/
|
|
#include <errno.h>
|
|
#include <netdb.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <time.h>
|
|
#include <netinet/in.h>
|
|
#include <arpa/inet.h>
|
|
#include <ctype.h>
|
|
#include <math.h>
|
|
#include <sys/socket.h>
|
|
#include <string.h>
|
|
#include <sys/types.h>
|
|
#include <assert.h>
|
|
|
|
#ifdef FORTIFY
|
|
#include "fortify.h"
|
|
#endif
|
|
|
|
#include "sinqhm.h"
|
|
#include "sinqhm.i"
|
|
|
|
/* missing in some network stuff?? */
|
|
|
|
#ifndef MSG_WAITALL
|
|
#define MSG_WAITALL 0
|
|
#endif
|
|
|
|
/* this may be a cludge for a missing prototype on Digital Unix */
|
|
extern int close(int fp);
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
static int SendDAQCommand(pSINQHM self, int iCommand, int *iDaq)
|
|
{
|
|
struct req_buff_struct Req_buff;
|
|
struct rply_buff_struct Rply_buff;
|
|
int status, iRet;
|
|
|
|
assert(self);
|
|
assert(self->iClientSocket);
|
|
|
|
/* prepare a message */
|
|
Req_buff.bigend = htonl (0x12345678);
|
|
Req_buff.cmnd = htonl (SQHM_DAQ);
|
|
Req_buff.u.daq.sub_cmnd = htonl (iCommand);
|
|
|
|
/* send the message */
|
|
status = send (self->iClientSocket, (char *) &Req_buff, sizeof (Req_buff), 0);
|
|
if (status == -1)
|
|
{
|
|
return SEND_ERROR;
|
|
}
|
|
if (status != sizeof (Req_buff))
|
|
{
|
|
return SEND_ERROR;
|
|
}
|
|
|
|
/* get a response */
|
|
status = recv (self->iClientSocket, (char *) &Rply_buff,
|
|
sizeof (Rply_buff), MSG_WAITALL);
|
|
|
|
/* check various error conditions */
|
|
if (status == -1)
|
|
{
|
|
return RECEIVE_ERROR;
|
|
}
|
|
if (status != sizeof (Rply_buff))
|
|
{
|
|
return INSUFFICIENT_DATA;
|
|
}
|
|
if(ntohl (Rply_buff.bigend) != 0x12345678)
|
|
{
|
|
return BYTE_ORDER_CHAOS;
|
|
}
|
|
if((iRet = ntohl (Rply_buff.status)) != KER__SUCCESS)
|
|
{
|
|
return SOFTWARE_ERROR;
|
|
}
|
|
|
|
*iDaq = ntohs (Rply_buff.u.daq.daq_now);
|
|
|
|
/* success */
|
|
return 1;
|
|
}
|
|
/*-----------------------------------------------------------------------*/
|
|
static int SendDAQStatus(pSINQHM self,
|
|
struct rply_buff_struct *pReply)
|
|
{
|
|
struct req_buff_struct Req_buff;
|
|
int status, iRet;
|
|
|
|
assert(self);
|
|
|
|
if(!self->iClientSocket)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
/* prepare a message */
|
|
Req_buff.bigend = htonl (0x12345678);
|
|
Req_buff.cmnd = htonl (SQHM_STATUS);
|
|
|
|
/* send the message */
|
|
status = send (self->iClientSocket, (char *) &Req_buff, sizeof (Req_buff), 0);
|
|
if (status == -1)
|
|
{
|
|
return SEND_ERROR;
|
|
}
|
|
if (status != sizeof (Req_buff))
|
|
{
|
|
return SEND_ERROR;
|
|
}
|
|
|
|
/* get a response */
|
|
status = recv (self->iClientSocket, (char *) pReply,
|
|
sizeof (struct rply_buff_struct), MSG_WAITALL);
|
|
|
|
/* check various error conditions */
|
|
if (status == -1)
|
|
{
|
|
return RECEIVE_ERROR;
|
|
}
|
|
if (status != sizeof (struct rply_buff_struct))
|
|
{
|
|
return INSUFFICIENT_DATA;
|
|
}
|
|
if(ntohl (pReply->bigend) != 0x12345678)
|
|
{
|
|
return BYTE_ORDER_CHAOS;
|
|
}
|
|
if((iRet = ntohl (pReply->status)) != KER__SUCCESS)
|
|
{
|
|
return SOFTWARE_ERROR;
|
|
}
|
|
|
|
/* success */
|
|
return 1;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
pSINQHM CreateSINQHM(char *pHMComputer, int iMasterPort)
|
|
{
|
|
pSINQHM pNew = NULL;
|
|
|
|
/* new memory */
|
|
pNew = (pSINQHM)malloc(sizeof(SINQHM));
|
|
if(!pNew)
|
|
{
|
|
return NULL;
|
|
}
|
|
memset(pNew,0,sizeof(SINQHM));
|
|
|
|
pNew->pHMComputer = strdup(pHMComputer);
|
|
pNew->iMasterPort = iMasterPort;
|
|
|
|
return pNew;
|
|
}
|
|
/*-----------------------------------------------------------------------*/
|
|
pSINQHM CopySINQHM(pSINQHM self)
|
|
{
|
|
pSINQHM pNew = NULL;
|
|
|
|
assert(self);
|
|
|
|
pNew = CreateSINQHM(self->pHMComputer,self->iMasterPort);
|
|
if(!pNew)
|
|
{
|
|
return NULL;
|
|
}
|
|
pNew->iBinWidth = self->iBinWidth;
|
|
pNew->iPacket = self->iPacket;
|
|
pNew->iRank = self->iRank;
|
|
pNew->iLength = self->iLength;
|
|
return pNew;
|
|
}
|
|
/*-------------------------------------------------------------------------*/
|
|
void SINQHMSetPar(pSINQHM self, int iRank, int iLength, int iBin)
|
|
{
|
|
assert(self);
|
|
|
|
self->iRank = iRank;
|
|
self->iLength = iLength;
|
|
self->iBinWidth = iBin;
|
|
}
|
|
/*-------------------------------------------------------------------------*/
|
|
void DeleteSINQHM(pSINQHM self)
|
|
{
|
|
int i;
|
|
|
|
assert(self);
|
|
|
|
if(self->pHMComputer)
|
|
{
|
|
free(self->pHMComputer);
|
|
}
|
|
|
|
for(i = 0; i < self->iBanks; i++)
|
|
{
|
|
if(self->pBank[i].iEdges)
|
|
{
|
|
free(self->pBank[i].iEdges);
|
|
}
|
|
}
|
|
|
|
/* make sure a possible clients connection gets murdered */
|
|
if(self->iClientSocket)
|
|
{
|
|
SINQHMCloseDAQ(self);
|
|
}
|
|
free(self);
|
|
}
|
|
/*------------------------------------------------------------------------*/
|
|
int SINQHMConfigure(pSINQHM self, int iMode, int iRank, int iLength,
|
|
int iBinWidth, int iLowBin, int iCompress)
|
|
{
|
|
int status, iRet;
|
|
struct req_buff_struct Req_buff;
|
|
struct rply_buff_struct Rply_buff;
|
|
|
|
assert(self);
|
|
|
|
/* branch specially for TOF flight mode */
|
|
if( (iMode >= SQHM__TOF) && (iMode < SQHM__HM_PSD) )
|
|
{
|
|
self->iBinWidth = iBinWidth;
|
|
return SINQHMTimeBin(self,iMode);
|
|
}
|
|
|
|
/* fill in the request data structure */
|
|
Req_buff.bigend = htonl (0x12345678);
|
|
Req_buff.cmnd = htonl (SQHM_CONFIG);
|
|
Req_buff.u.cnfg.mode = htonl (iMode);
|
|
Req_buff.u.cnfg.u.hm_dig.n_hists = htonl (iRank);
|
|
printf("%d\n", ntohl(Req_buff.u.cnfg.u.hm_dig.n_hists));
|
|
Req_buff.u.cnfg.u.hm_dig.lo_bin = htonl (iLowBin);
|
|
Req_buff.u.cnfg.u.hm_dig.num_bins = htonl (iLength);
|
|
Req_buff.u.cnfg.u.hm_dig.bytes_per_bin = htonl (iBinWidth);
|
|
Req_buff.u.cnfg.u.hm_dig.compress = htonl (iCompress);
|
|
|
|
/* try, get a connection to master server */
|
|
status = OpenMasterConnection(self);
|
|
if(status < 0)
|
|
{
|
|
return status;
|
|
}
|
|
|
|
/* send request */
|
|
status = send(self->iMasterSocket,(char *)&Req_buff, sizeof(Req_buff),0);
|
|
if(status == -1)
|
|
{
|
|
return SEND_ERROR;
|
|
}
|
|
|
|
/* get a reply */
|
|
iRet = GetMasterReply(self,&Rply_buff,sizeof(Rply_buff));
|
|
if(iRet < 0)
|
|
{
|
|
/* try close the socket */
|
|
close(self->iMasterSocket);
|
|
self->iMasterSocket = 0;
|
|
return iRet;
|
|
}
|
|
else
|
|
{
|
|
/* configure successful, keep the data */
|
|
self->iBinWidth = iBinWidth;
|
|
self->iLength = iLength;
|
|
self->iRank = iRank;
|
|
|
|
/* close the socket */
|
|
status = close(self->iMasterSocket);
|
|
self->iMasterSocket = 0;
|
|
if((status != 0) && (errno != ECONNRESET))
|
|
{
|
|
return CLOSE_ERROR;
|
|
}
|
|
}
|
|
return 1; /* success, finally */
|
|
}
|
|
/*------------------------------------------------------------------------*/
|
|
int SINQHMConfigurePSD(pSINQHM self, int iMode,
|
|
int xSize, int xOff, int xFac,
|
|
int ySize, int yOff, int yFac,
|
|
int iBinWidth,
|
|
float *iEdges, int iEdgeLength)
|
|
{
|
|
int status, iRet;
|
|
struct req_buff_struct Req_buff;
|
|
struct rply_buff_struct Rply_buff;
|
|
int iLength, i, iDelay;
|
|
unsigned int iExtra;
|
|
char *pBuffer = NULL, *pPtr;
|
|
struct tof_edge_arr tea;
|
|
int iTeaLength;
|
|
struct tof_bank toba;
|
|
|
|
assert(self);
|
|
|
|
/* set up detector bank information. This code supports only
|
|
one detector bank as of now. Which is appropriate for the
|
|
detector at hand.
|
|
*/
|
|
self->iBinWidth = iBinWidth;
|
|
SINQHMDefineBank(self,0,0,xSize*ySize,
|
|
iEdges,iEdgeLength);
|
|
|
|
/* figure out how long we are going to be*/
|
|
iLength = 36 + self->iBanks*sizeof(struct tof_bank);
|
|
for(i = 0; i < self->iBanks; i++)
|
|
{
|
|
iLength += 8 + self->pBank[i].iEdgeLength*sizeof(SQint32);
|
|
}
|
|
if(iLength < 64)
|
|
iLength = 64;
|
|
/* allocate send buffer */
|
|
pBuffer = (char *)malloc(iLength*sizeof(char));
|
|
if(!pBuffer)
|
|
{
|
|
return HIST_BAD_ALLOC;
|
|
}
|
|
memset(pBuffer,0,iLength);
|
|
|
|
/* do the message header */
|
|
iExtra = iLength - sizeof(Req_buff);
|
|
if(iExtra < 0)
|
|
iExtra = 0;
|
|
iDelay = self->pBank[0].iEdges[0];
|
|
Req_buff.bigend = htonl (0x12345678);
|
|
Req_buff.cmnd = htonl (SQHM_CONFIG);
|
|
Req_buff.u.cnfg.mode = htonl (iMode);
|
|
Req_buff.u.cnfg.u.psd.n_extra_bytes = htonl (iExtra);
|
|
Req_buff.u.cnfg.u.psd.n_edges = htons (1);
|
|
Req_buff.u.cnfg.u.psd.n_banks = htons (1);
|
|
Req_buff.u.cnfg.u.psd.xOffset = htons (xOff);
|
|
Req_buff.u.cnfg.u.psd.yOffset = htons (yOff);
|
|
Req_buff.u.cnfg.u.psd.xFactor = htons (xFac);
|
|
Req_buff.u.cnfg.u.psd.yFactor = htons (yFac);
|
|
Req_buff.u.cnfg.u.psd.xSize = htons (xSize);
|
|
Req_buff.u.cnfg.u.psd.ySize = htons (ySize);
|
|
Req_buff.u.cnfg.u.psd.preset_delay = htonl((int)iEdges[0]);
|
|
memcpy(pBuffer,&Req_buff,36);
|
|
pPtr = pBuffer + 36;
|
|
|
|
/* do the edge thingies */
|
|
for(i = 0; i < self->iBanks; i++)
|
|
{
|
|
tea.n_bins = htonl(self->pBank[i].iEdgeLength-1);
|
|
if(self->pBank[i].iEdgeLength == 2)
|
|
{
|
|
tea.flag = htonl(0);
|
|
}
|
|
else
|
|
{
|
|
tea.flag = htonl(1);
|
|
}
|
|
tea.edges = self->pBank[i].iEdges;
|
|
memcpy(pPtr,&tea,8);
|
|
pPtr += 8;
|
|
iTeaLength = self->pBank[i].iEdgeLength*4;
|
|
memcpy(pPtr,self->pBank[i].iEdges,iTeaLength);
|
|
pPtr += iTeaLength;
|
|
}
|
|
|
|
/* do the swiss bank structures */
|
|
for(i = 0; i < self->iBanks; i++)
|
|
{
|
|
toba.first = htons(self->pBank[i].iStart);
|
|
toba.n_cntrs = htons(self->pBank[i].iEnd);
|
|
toba.edge_indx = htons(i);
|
|
toba.bytes_per_bin = htons(self->iBinWidth);
|
|
memcpy(pPtr,&toba,sizeof(struct tof_bank));
|
|
pPtr += sizeof(struct tof_bank);
|
|
}
|
|
|
|
/* all packed up neat and nicely, send it */
|
|
/* try, get a connection to master server */
|
|
status = OpenMasterConnection(self);
|
|
if(status < 0)
|
|
{
|
|
if(pBuffer)
|
|
free(pBuffer);
|
|
return status;
|
|
}
|
|
|
|
/* send request */
|
|
status = send(self->iMasterSocket,pBuffer,iLength ,0);
|
|
if(pBuffer)
|
|
{
|
|
free(pBuffer);
|
|
}
|
|
if(status == -1)
|
|
{
|
|
return SEND_ERROR;
|
|
}
|
|
|
|
/* get a reply */
|
|
iRet = GetMasterReply(self,&Rply_buff,sizeof(Rply_buff));
|
|
if(iRet < 0)
|
|
{
|
|
/* try close the socket */
|
|
close(self->iMasterSocket);
|
|
self->iMasterSocket = 0;
|
|
return iRet;
|
|
}
|
|
else
|
|
{
|
|
/* close the socket */
|
|
status = close(self->iMasterSocket);
|
|
self->iMasterSocket = 0;
|
|
if((status != 0) && (errno != ECONNRESET))
|
|
{
|
|
return CLOSE_ERROR;
|
|
}
|
|
}
|
|
return 1; /* success, finally */
|
|
}
|
|
/*------------------------------------------------------------------------*/
|
|
int SINQHMDeconfigure(pSINQHM self, int iHarsh)
|
|
{
|
|
int status, iRet;
|
|
struct req_buff_struct Req_buff;
|
|
struct rply_buff_struct Rply_buff;
|
|
|
|
assert(self);
|
|
if( (iHarsh != 0) && (iHarsh != 1) )
|
|
{
|
|
return INVALID_HARSH;
|
|
}
|
|
|
|
/* fill in the request data structure */
|
|
Req_buff.bigend = htonl (0x12345678);
|
|
Req_buff.cmnd = htonl (SQHM_DECONFIG);
|
|
Req_buff.u.decnfg.sub_code = htonl(iHarsh);
|
|
|
|
/* try, get a connection to master server */
|
|
status = OpenMasterConnection(self);
|
|
if(status < 0)
|
|
{
|
|
return status;
|
|
}
|
|
|
|
/* send request */
|
|
status = send(self->iMasterSocket,(char *)&Req_buff, sizeof(Req_buff),0);
|
|
if(status == -1)
|
|
{
|
|
return SEND_ERROR;
|
|
}
|
|
|
|
/* get a reply */
|
|
iRet = GetMasterReply(self,&Rply_buff,sizeof(Rply_buff));
|
|
if(iRet < 0)
|
|
{
|
|
close(self->iMasterSocket);
|
|
self->iMasterSocket = 0;
|
|
return iRet;
|
|
}
|
|
else
|
|
{
|
|
status = close(self->iMasterSocket);
|
|
self->iMasterSocket = 0;
|
|
if((status != 0) && (errno != ECONNRESET))
|
|
{
|
|
return CLOSE_ERROR;
|
|
}
|
|
}
|
|
return 1; /* success, finally */
|
|
}
|
|
/*------------------------------------------------------------------------*/
|
|
int SINQHMGetStatus(pSINQHM self, int *iMode,int *iDaq,
|
|
int *iRank, int *iBinWidth,
|
|
int *iLength, int *iClients)
|
|
{
|
|
int status, iRet;
|
|
short sDaq, sFill;
|
|
struct req_buff_struct Req_buff;
|
|
struct rply_buff_struct Rply_buff;
|
|
|
|
assert(self);
|
|
|
|
|
|
status = 0;
|
|
if(self->iClientSocket)
|
|
{
|
|
status = SendDAQStatus(self,&Rply_buff);
|
|
}
|
|
else
|
|
{
|
|
/* fill in the request data structure */
|
|
Req_buff.bigend = htonl (0x12345678);
|
|
Req_buff.cmnd = htonl (SQHM_STATUS);
|
|
|
|
/* try, get a connection to master server */
|
|
status = OpenMasterConnection(self);
|
|
if(status < 0)
|
|
{
|
|
return status;
|
|
}
|
|
|
|
/* send request */
|
|
status = send(self->iMasterSocket,(char *)&Req_buff, sizeof(Req_buff),0);
|
|
if(status == -1)
|
|
{
|
|
return SEND_ERROR;
|
|
}
|
|
|
|
/* get a reply */
|
|
iRet = GetMasterReply(self,&Rply_buff,sizeof(Rply_buff));
|
|
if(iRet < 0)
|
|
{
|
|
close(self->iMasterSocket);
|
|
self->iMasterSocket = 0;
|
|
return iRet;
|
|
}
|
|
else
|
|
{
|
|
status = 1;
|
|
/* close the socket and go */
|
|
iRet = close(self->iMasterSocket);
|
|
self->iMasterSocket = 0;
|
|
if((iRet != 0) && (errno != ECONNRESET))
|
|
{
|
|
return CLOSE_ERROR;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(status)
|
|
{
|
|
/* transfer results */
|
|
*iMode = ntohl(Rply_buff.u.status.cfg_state);
|
|
if((sDaq = ntohs(Rply_buff.u.status.daq_now)) == 0) /* DAQ active */
|
|
{
|
|
*iDaq = 1;
|
|
}
|
|
else
|
|
{
|
|
sFill = ntohs(Rply_buff.u.status.filler_mask);
|
|
if(sFill & sDaq)
|
|
{
|
|
/* filler is not running */
|
|
*iDaq = 0;
|
|
}
|
|
else
|
|
{
|
|
/* inhibited by some mean client */
|
|
*iDaq = 2;
|
|
}
|
|
}
|
|
*iRank = ntohs(Rply_buff.u.status.n_hists);
|
|
*iLength = ntohl(Rply_buff.u.status.num_bins);
|
|
*iBinWidth = Rply_buff.u.status.bytes_per_bin;
|
|
*iClients = Rply_buff.u.status.act_srvrs;
|
|
}
|
|
return 1; /* success, finally */
|
|
}
|
|
/*------------------------------------------------------------------------*/
|
|
int SINQHMDebug(pSINQHM self, int iLevel)
|
|
{
|
|
int status, iRet;
|
|
struct req_buff_struct Req_buff;
|
|
struct rply_buff_struct Rply_buff;
|
|
|
|
assert(self);
|
|
|
|
/* fill in the request data structure */
|
|
Req_buff.bigend = htonl (0x12345678);
|
|
Req_buff.cmnd = htonl (SQHM_DBG);
|
|
Req_buff.u.dbg.mask = htonl(iLevel);
|
|
|
|
/* try, get a connection to master server */
|
|
status = OpenMasterConnection(self);
|
|
if(status < 0)
|
|
{
|
|
return status;
|
|
}
|
|
|
|
/* send request */
|
|
status = send(self->iMasterSocket,(char *)&Req_buff, sizeof(Req_buff),0);
|
|
if(status == -1)
|
|
{
|
|
return SEND_ERROR;
|
|
}
|
|
|
|
/* get a reply */
|
|
iRet = GetMasterReply(self,&Rply_buff,sizeof(Rply_buff));
|
|
if(iRet < 0)
|
|
{
|
|
close(self->iMasterSocket);
|
|
self->iMasterSocket = 0;
|
|
return iRet;
|
|
}
|
|
else
|
|
{
|
|
status = close(self->iMasterSocket);
|
|
self->iMasterSocket = 0;
|
|
if((status != 0) && (errno != ECONNRESET))
|
|
{
|
|
return CLOSE_ERROR;
|
|
}
|
|
}
|
|
return 1; /* success, finally */
|
|
}
|
|
/*------------------------------------------------------------------------*/
|
|
int SINQHMKill(pSINQHM self)
|
|
{
|
|
int status, iRet;
|
|
struct req_buff_struct Req_buff;
|
|
struct rply_buff_struct Rply_buff;
|
|
|
|
assert(self);
|
|
|
|
/* fill in the request data structure */
|
|
Req_buff.bigend = htonl (0x12345678);
|
|
Req_buff.cmnd = htonl (SQHM_EXIT);
|
|
|
|
/* try, get a connection to master server */
|
|
status = OpenMasterConnection(self);
|
|
if(status < 0)
|
|
{
|
|
return status;
|
|
}
|
|
|
|
/* send request */
|
|
status = send(self->iMasterSocket,(char *)&Req_buff, sizeof(Req_buff),0);
|
|
if(status == -1)
|
|
{
|
|
return SEND_ERROR;
|
|
}
|
|
|
|
/* get a reply */
|
|
iRet = GetMasterReply(self,&Rply_buff,sizeof(Rply_buff));
|
|
if(iRet < 0)
|
|
{
|
|
close(self->iMasterSocket);
|
|
self->iMasterSocket = 0;
|
|
return iRet;
|
|
}
|
|
else
|
|
{
|
|
status = close(self->iMasterSocket);
|
|
self->iMasterSocket = 0;
|
|
if((status != 0) && (errno != ECONNRESET))
|
|
{
|
|
return CLOSE_ERROR;
|
|
}
|
|
}
|
|
return 1; /* success, finally */
|
|
}
|
|
|
|
/*====================== DAQ functions ==================================*/
|
|
int SINQHMOpenDAQ(pSINQHM self)
|
|
{
|
|
int status, iRet, iPacket;
|
|
struct sockaddr_in lcl_sockname;
|
|
struct sockaddr_in rmt_sockname;
|
|
struct hostent *rmt_hostent;
|
|
struct in_addr *rmt_inet_addr_pntr;
|
|
struct req_buff_struct Req_buff;
|
|
struct rply_buff_struct Rply_buff;
|
|
|
|
assert(self);
|
|
|
|
/* fill in the request data structure */
|
|
Req_buff.bigend = htonl (0x12345678);
|
|
Req_buff.cmnd = htonl (SQHM_CNCT);
|
|
Req_buff.u.cnct.max_pkt = htonl (8192);
|
|
Req_buff.u.cnct.strt_mode = htonl (0);
|
|
|
|
|
|
/* try, get a connection to master server */
|
|
status = OpenMasterConnection(self);
|
|
if(status < 0)
|
|
{
|
|
return status;
|
|
}
|
|
|
|
/* send request */
|
|
status = send(self->iMasterSocket,(char *)&Req_buff, sizeof(Req_buff),0);
|
|
if(status == -1)
|
|
{
|
|
return SEND_ERROR;
|
|
}
|
|
|
|
/* get a reply */
|
|
iRet = GetMasterReply(self,&Rply_buff,sizeof(Rply_buff));
|
|
status = close(self->iMasterSocket);
|
|
self->iMasterSocket = 0;
|
|
if(iRet < 0)
|
|
{
|
|
return iRet;
|
|
}
|
|
if(status != 0)
|
|
{
|
|
return CLOSE_ERROR;
|
|
}
|
|
|
|
/* read the port and packet size to use */
|
|
self->iClientPort = ntohl (Rply_buff.u.cnct.port);
|
|
iPacket = ntohl (Rply_buff.u.cnct.pkt_size);
|
|
self->iPacket = iPacket;
|
|
|
|
/* now we are ready to open the connection to our very own histogram
|
|
memory slave server
|
|
*/
|
|
|
|
/* first a socket */
|
|
self->iClientSocket = socket (AF_INET, SOCK_STREAM, 0);
|
|
if(self->iClientSocket == -1)
|
|
{
|
|
return SOCKET_ERROR;
|
|
}
|
|
|
|
/* now try a bind */
|
|
lcl_sockname.sin_family = AF_INET;
|
|
lcl_sockname.sin_port = htons (0);
|
|
lcl_sockname.sin_addr.s_addr = 0;
|
|
status = bind (self->iClientSocket, (struct sockaddr *) &lcl_sockname,
|
|
sizeof (lcl_sockname));
|
|
if (status == -1)
|
|
{
|
|
self->iClientSocket = 0;
|
|
return BIND_ERROR;
|
|
}
|
|
|
|
/* get hostname (again). This is double work (has happened in
|
|
OpenMasterConnection before) but I decided for this in order to
|
|
avoid carrying that extra adress pointer needed for connect around.
|
|
*/
|
|
rmt_hostent = gethostbyname (self->pHMComputer);
|
|
if (rmt_hostent == NULL) {
|
|
/* this should never happen, as we got it recently in
|
|
OpenMasterConnection
|
|
*/
|
|
return HMCOMPUTER_NOT_FOUND;
|
|
}
|
|
rmt_inet_addr_pntr = (struct in_addr *) rmt_hostent->h_addr_list[0];
|
|
|
|
/* and connect */
|
|
rmt_sockname.sin_family = AF_INET;
|
|
rmt_sockname.sin_port = htons (self->iClientPort);
|
|
rmt_sockname.sin_addr.s_addr = rmt_inet_addr_pntr->s_addr;
|
|
status = connect (self->iClientSocket, (struct sockaddr *) &rmt_sockname,
|
|
sizeof (rmt_sockname));
|
|
if (status == -1)
|
|
{
|
|
self->iClientSocket = 0;
|
|
return CONNECT_ERROR;
|
|
}
|
|
|
|
/* done! Surprise! Everything worked! */
|
|
return 1;
|
|
}
|
|
/*------------------------------------------------------------------------*/
|
|
int SINQHMCloseDAQ(pSINQHM self)
|
|
{
|
|
struct req_buff_struct Req_buff;
|
|
int status, iRet;
|
|
|
|
assert(self);
|
|
if(self->iClientSocket <= 0)
|
|
{
|
|
/* already colsed */
|
|
return 1;
|
|
}
|
|
|
|
iRet = 1;
|
|
|
|
/* send close message, this helps the master to clean up */
|
|
Req_buff.bigend = htonl (0x12345678);
|
|
Req_buff.cmnd = htonl (SQHM_CLOSE);
|
|
status = send (self->iClientSocket, (char *) &Req_buff, sizeof (Req_buff), 0);
|
|
if (status == -1)
|
|
{
|
|
iRet = SEND_ERROR;
|
|
}
|
|
if (status != sizeof (Req_buff))
|
|
{
|
|
iRet = SEND_ERROR;
|
|
}
|
|
status = close (self->iClientSocket);
|
|
if (status != 0)
|
|
{
|
|
iRet = CLOSE_ERROR;
|
|
}
|
|
self->iClientSocket = 0;
|
|
self->iClientPort = 0;
|
|
return iRet;
|
|
}
|
|
/*-----------------------------------------------------------------------*/
|
|
int SINQHMStartDAQ(pSINQHM self)
|
|
{
|
|
int status, iDaq;
|
|
|
|
assert(self);
|
|
|
|
status = SendDAQCommand(self,DAQ__GO,&iDaq);
|
|
if(status < 0) /* error */
|
|
{
|
|
return status;
|
|
}
|
|
if(iDaq != 0)
|
|
{
|
|
return DAQ_INHIBIT;
|
|
}
|
|
return 1;
|
|
}
|
|
/*-----------------------------------------------------------------------*/
|
|
int SINQHMStopDAQ(pSINQHM self)
|
|
{
|
|
int status, iDaq;
|
|
|
|
assert(self);
|
|
|
|
status = SendDAQCommand(self,DAQ__STOP,&iDaq);
|
|
if(status < 0) /* error */
|
|
{
|
|
return status;
|
|
}
|
|
if(iDaq == 0)
|
|
{
|
|
return DAQ_NOTSTOPPED;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
int SINQHMContinueDAQ(pSINQHM self)
|
|
{
|
|
int status, iDaq;
|
|
|
|
assert(self);
|
|
|
|
status = SendDAQCommand(self,DAQ__CLR,&iDaq);
|
|
if(status < 0) /* error */
|
|
{
|
|
return status;
|
|
}
|
|
if(iDaq != 0)
|
|
{
|
|
return DAQ_INHIBIT;
|
|
}
|
|
return 1;
|
|
}
|
|
/*-----------------------------------------------------------------------*/
|
|
int SINQHMInhibitDAQ(pSINQHM self)
|
|
{
|
|
int status, iDaq;
|
|
|
|
assert(self);
|
|
|
|
status = SendDAQCommand(self,DAQ__INH,&iDaq);
|
|
if(status < 0) /* error */
|
|
{
|
|
return status;
|
|
}
|
|
if(iDaq == 0)
|
|
{
|
|
return DAQ_NOTSTOPPED;
|
|
}
|
|
return 1;
|
|
|
|
}
|
|
/*-----------------------------------------------------------------------*/
|
|
int SINQHMWrite(pSINQHM self, int iNum, int iStart, int iEnd, void *pData)
|
|
{
|
|
long lBytes2Go,lBins, i;
|
|
int status, iRet;
|
|
struct req_buff_struct Req_buff;
|
|
struct rply_buff_struct Rply_buff;
|
|
SQint16 *p16;
|
|
SQint32 *p32;
|
|
char *pPtr;
|
|
|
|
assert(self);
|
|
|
|
/* calculate number of bins */
|
|
lBins = iEnd;
|
|
|
|
/* take care of byte order first */
|
|
if (0x12345678 != ntohl (0x12345678))
|
|
{
|
|
/* Swap bytes, if necessary */
|
|
switch (self->iBinWidth)
|
|
{
|
|
case 1:
|
|
break;
|
|
case 2:
|
|
p16 = (SQint16 *) pData;
|
|
for (i=0; i < lBins; i++)
|
|
{
|
|
p16[i] = htons (p16[i]);
|
|
}
|
|
break;
|
|
case 4:
|
|
p32 = (SQint32 *) pData;
|
|
for (i=0; i < lBins; i++)
|
|
{
|
|
p32[i] = htonl (p32[i]);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* initialize the Request data */
|
|
Req_buff.bigend = htonl (0x12345678);
|
|
Req_buff.cmnd = htonl (SQHM_WRITE);
|
|
Req_buff.u.write.n_bins = htonl (lBins);
|
|
Req_buff.u.write.first_bin = htonl (iStart);
|
|
Req_buff.u.write.bytes_per_bin = htonl (self->iBinWidth);
|
|
Req_buff.u.write.hist_no = htonl (iNum);
|
|
|
|
/* send the message */
|
|
status = send (self->iClientSocket, (char *) &Req_buff, sizeof (Req_buff), 0);
|
|
if (status == -1)
|
|
{
|
|
return SEND_ERROR;
|
|
}
|
|
if (status != sizeof (Req_buff))
|
|
{
|
|
return SEND_ERROR;
|
|
}
|
|
|
|
/* send data */
|
|
lBytes2Go = lBins * self->iBinWidth;
|
|
pPtr = (char *)pData;
|
|
while (lBytes2Go > 0)
|
|
{
|
|
i = (lBytes2Go > self->iPacket) ? self->iPacket : lBytes2Go;
|
|
status = send (self->iClientSocket, (char *) pPtr, i, 0);
|
|
if (status <= 0)
|
|
{
|
|
return SEND_ERROR;
|
|
}
|
|
lBytes2Go -= status;
|
|
pPtr += status;
|
|
}
|
|
|
|
/* get status */
|
|
status = recv (self->iClientSocket, (char *) &Rply_buff,
|
|
sizeof (Rply_buff), MSG_WAITALL);
|
|
|
|
/* check various error conditions */
|
|
if (status == -1)
|
|
{
|
|
return RECEIVE_ERROR;
|
|
}
|
|
if (status != sizeof (Rply_buff))
|
|
{
|
|
return INSUFFICIENT_DATA;
|
|
}
|
|
if(ntohl (Rply_buff.bigend) != 0x12345678)
|
|
{
|
|
return BYTE_ORDER_CHAOS;
|
|
}
|
|
if((iRet = ntohl (Rply_buff.status)) == KER__BAD_VALUE)
|
|
{
|
|
return HIST_BAD_VALUE;
|
|
}
|
|
if(iRet != KER__SUCCESS)
|
|
{
|
|
return HIST_BAD_CODE;
|
|
}
|
|
/* success */
|
|
return 1;
|
|
}
|
|
/*-----------------------------------------------------------------------*/
|
|
int SINQHMRead(pSINQHM self, int iNum, int iStart, int iEnd,
|
|
void *pData, int iDataLen)
|
|
{
|
|
long lBins2Get, lSpace,iNoBins, i;
|
|
int status, iRet;
|
|
struct req_buff_struct Req_buff;
|
|
struct rply_buff_struct Rply_buff;
|
|
SQint16 *p16;
|
|
SQint32 *p32;
|
|
char *pPtr;
|
|
char pBuffer[8192];
|
|
|
|
assert(self);
|
|
|
|
/* initialize the Request data */
|
|
Req_buff.bigend = htonl (0x12345678);
|
|
Req_buff.cmnd = htonl (SQHM_READ);
|
|
Req_buff.u.read.n_bins = htonl (iEnd);
|
|
Req_buff.u.read.first_bin = htonl (iStart);
|
|
Req_buff.u.read.hist_no = htonl (iNum);
|
|
|
|
/* send the message */
|
|
status = send (self->iClientSocket, (char *) &Req_buff,
|
|
sizeof (Req_buff), 0);
|
|
if (status == -1)
|
|
{
|
|
return SEND_ERROR;
|
|
}
|
|
if (status != sizeof (Req_buff))
|
|
{
|
|
return SEND_ERROR;
|
|
}
|
|
|
|
/* wait for an answer */
|
|
status = recv (self->iClientSocket, (char *) &Rply_buff,
|
|
sizeof (Rply_buff), MSG_WAITALL);
|
|
|
|
/* check various error conditions */
|
|
if (status == -1)
|
|
{
|
|
return RECEIVE_ERROR;
|
|
}
|
|
if (status != sizeof (Rply_buff))
|
|
{
|
|
return INSUFFICIENT_DATA;
|
|
}
|
|
if(ntohl (Rply_buff.bigend) != 0x12345678)
|
|
{
|
|
return BYTE_ORDER_CHAOS;
|
|
}
|
|
iRet = ntohl(Rply_buff.status);
|
|
if(iRet != KER__SUCCESS)
|
|
{
|
|
return HIST_BAD_CODE;
|
|
}
|
|
|
|
/* calculate the size of things to come */
|
|
lBins2Get = ntohl(Rply_buff.u.read.n_bins) * ntohl(Rply_buff.u.read.bytes_per_bin);
|
|
|
|
/* read data */
|
|
pPtr = (char *)pData;
|
|
lSpace = iDataLen;
|
|
iNoBins = ntohl(Rply_buff.u.read.n_bins);
|
|
while (lBins2Get > 0)
|
|
{
|
|
if(lBins2Get > self->iPacket)
|
|
{
|
|
i = self->iPacket;
|
|
}
|
|
else
|
|
{
|
|
i = lBins2Get;
|
|
}
|
|
status = recv (self->iClientSocket, pBuffer,
|
|
i, 0);
|
|
if (status == -1)
|
|
{
|
|
return SEND_ERROR;
|
|
}
|
|
lBins2Get -= status;
|
|
if((lSpace - status) > 0)
|
|
{
|
|
memcpy(pPtr,pBuffer,status);
|
|
lSpace -= status;
|
|
pPtr += status;
|
|
}
|
|
else
|
|
{
|
|
if(lSpace > 0)
|
|
{
|
|
memcpy(pPtr,pBuffer,lSpace);
|
|
lSpace = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* swap bytes if necessary */
|
|
if ((self->iBinWidth > 0) && (Rply_buff.bigend != 0x12345678))
|
|
{
|
|
switch (self->iBinWidth)
|
|
{ /* Byte swapping is necessary */
|
|
case 2:
|
|
/* Not sure how to do this - this might be wrong! */
|
|
p16 = (SQint16 *) pData;
|
|
for (i = 0; i < iNoBins; i++)
|
|
{
|
|
p16[i] = ntohs (p16[i]);
|
|
}
|
|
break;
|
|
case 4:
|
|
p32 = (SQint32 *) pData;
|
|
for (i = 0; i < iNoBins; i++)
|
|
{
|
|
p32[i] = ntohl(p32[i]);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
/* done */
|
|
return 1;
|
|
}
|
|
/*------------------------------------------------------------------------*/
|
|
int SINQHMZero(pSINQHM self, int iNumber, int iStart, int iEnd)
|
|
{
|
|
int status, iRet;
|
|
struct req_buff_struct Req_buff;
|
|
struct rply_buff_struct Rply_buff;
|
|
|
|
assert(self);
|
|
|
|
/* fill in the request data structure */
|
|
Req_buff.bigend = htonl (0x12345678);
|
|
Req_buff.cmnd = htonl (SQHM_ZERO);
|
|
Req_buff.u.zero.hist_no = htonl (iNumber);
|
|
Req_buff.u.zero.first_bin = htonl (iStart);
|
|
Req_buff.u.zero.n_bins = htonl (iEnd);
|
|
|
|
/* try, get a connection to master server */
|
|
status = OpenMasterConnection(self);
|
|
if(status < 0)
|
|
{
|
|
return status;
|
|
}
|
|
|
|
/* send request */
|
|
status = send(self->iMasterSocket,(char *)&Req_buff, sizeof(Req_buff),0);
|
|
if(status == -1)
|
|
{
|
|
return SEND_ERROR;
|
|
}
|
|
|
|
/* get a reply */
|
|
iRet = GetMasterReply(self,&Rply_buff,sizeof(Rply_buff));
|
|
if(iRet < 0)
|
|
{
|
|
close(self->iMasterSocket);
|
|
self->iMasterSocket = 0;
|
|
return iRet;
|
|
}
|
|
else
|
|
{
|
|
status = close(self->iMasterSocket);
|
|
self->iMasterSocket = 0;
|
|
if((status != 0) && (errno != ECONNRESET))
|
|
{
|
|
return CLOSE_ERROR;
|
|
}
|
|
}
|
|
return 1; /* success, finally */
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
static int OpenMasterConnection(pSINQHM self)
|
|
{
|
|
struct hostent *rmt_hostent;
|
|
struct sockaddr_in lcl_sockname;
|
|
int rmt_sockname_len;
|
|
struct sockaddr_in rmt_sockname;
|
|
struct in_addr *rmt_inet_addr_pntr;
|
|
int status;
|
|
|
|
|
|
/* get hostname */
|
|
rmt_hostent = gethostbyname (self->pHMComputer);
|
|
if (rmt_hostent == NULL) {
|
|
return HMCOMPUTER_NOT_FOUND;
|
|
}
|
|
rmt_inet_addr_pntr = (struct in_addr *) rmt_hostent->h_addr_list[0];
|
|
|
|
|
|
/* try, open socket */
|
|
self->iMasterSocket = socket (AF_INET, SOCK_STREAM, 0);
|
|
if (self->iMasterSocket == -1)
|
|
{
|
|
return SOCKET_ERROR;
|
|
}
|
|
|
|
/* bind it */
|
|
lcl_sockname.sin_family = AF_INET;
|
|
lcl_sockname.sin_port = htons(0);
|
|
lcl_sockname.sin_addr.s_addr = 0;
|
|
status = bind (self->iMasterSocket, (struct sockaddr *) &lcl_sockname,
|
|
sizeof (lcl_sockname));
|
|
if (status == -1)
|
|
{
|
|
return BIND_ERROR;
|
|
}
|
|
|
|
/* try to connect */
|
|
rmt_sockname_len = sizeof (rmt_sockname);
|
|
rmt_sockname.sin_family = AF_INET;
|
|
rmt_sockname.sin_port = htons (self->iMasterPort);
|
|
rmt_sockname.sin_addr.s_addr = rmt_inet_addr_pntr->s_addr;
|
|
status = connect (self->iMasterSocket, (struct sockaddr *) &rmt_sockname,
|
|
sizeof (rmt_sockname));
|
|
if (status == -1) {
|
|
return CONNECT_ERROR;
|
|
}
|
|
|
|
/* Success */
|
|
return 1;
|
|
}
|
|
/*------------------------------------------------------------------------*/
|
|
static int GetMasterReply(pSINQHM self, struct rply_buff_struct *reply,
|
|
int iBufLen)
|
|
{
|
|
|
|
int status;
|
|
|
|
assert(self->iMasterSocket);
|
|
|
|
/* get reply structure */
|
|
status = recv (self->iMasterSocket, (char *) reply,
|
|
iBufLen, MSG_WAITALL);
|
|
if (status == -1) {
|
|
return RECEIVE_ERROR;
|
|
} else if (status != iBufLen) {
|
|
return INSUFFICIENT_DATA;
|
|
}
|
|
|
|
/* check endedness */
|
|
if (ntohl (reply->bigend) != 0x12345678) {
|
|
return BYTE_ORDER_CHAOS;
|
|
}
|
|
|
|
/* check histogram memory status codes */
|
|
status = ntohl (reply->status);
|
|
if (status == KER__SUCCESS) {
|
|
return 1;
|
|
}else if (status == KER__BAD_CREATE) {
|
|
return HIST_BAD_CREATE;
|
|
}else if (status == KER__BAD_STATE) {
|
|
return HIST_BAD_STATE;
|
|
}else if (status == KER__BAD_VALUE) {
|
|
return HIST_BAD_VALUE;
|
|
}else if (status == KER__BAD_RECV) {
|
|
return HIST_BAD_RECV;
|
|
}else if (status == KER__BAD_ALLOC) {
|
|
return HIST_BAD_ALLOC;
|
|
}else {
|
|
return HIST_BAD_CODE;
|
|
}
|
|
/* not reached, usually */
|
|
return HIST_BAD_CODE;
|
|
}
|
|
/*-------------------------------------------------------------------------*/
|
|
int SINQHMError2Text(int iErr, char *pBuffer, int iBufLen)
|
|
{
|
|
/* the trivial case */
|
|
if(iErr > 0)
|
|
{
|
|
strncpy(pBuffer,"No error ocurred",iBufLen);
|
|
return 0;
|
|
}
|
|
|
|
switch(iErr)
|
|
{
|
|
case HMCOMPUTER_NOT_FOUND:
|
|
strncpy(pBuffer,
|
|
"No name server entry for histogram memory computer",
|
|
iBufLen);
|
|
break;
|
|
case SOCKET_ERROR:
|
|
strncpy(pBuffer,
|
|
"Insufficient system resources for socket creation",
|
|
iBufLen);
|
|
break;
|
|
case BIND_ERROR:
|
|
strncpy(pBuffer,
|
|
"Cannot bind",
|
|
iBufLen);
|
|
break;
|
|
case CONNECT_ERROR:
|
|
strncpy(pBuffer,
|
|
"Cannot connect, probably port number wrong",
|
|
iBufLen);
|
|
break;
|
|
case RECEIVE_ERROR:
|
|
strncpy(pBuffer,
|
|
"Error receiving data", iBufLen);
|
|
break;
|
|
case INSUFFICIENT_DATA:
|
|
strncpy(pBuffer,
|
|
"Not enough bytes received from host, network trouble",
|
|
iBufLen);
|
|
break;
|
|
case BYTE_ORDER_CHAOS:
|
|
strncpy(pBuffer,
|
|
"Reply not in network byte order",
|
|
iBufLen);
|
|
break;
|
|
case HIST_BAD_CREATE:
|
|
strncpy(pBuffer,
|
|
"Master histogram server failed to spawn child",
|
|
iBufLen);
|
|
break;
|
|
case HIST_BAD_VALUE:
|
|
strncpy(pBuffer,
|
|
"Invalid parameter detected",
|
|
iBufLen);
|
|
break;
|
|
case HIST_BAD_STATE:
|
|
strncpy(pBuffer,
|
|
"Histogram memory NOT configured",
|
|
iBufLen);
|
|
break;
|
|
case HIST_BAD_RECV:
|
|
strncpy(pBuffer,
|
|
"Histogram server failed to read command",
|
|
iBufLen);
|
|
break;
|
|
case HIST_BAD_ALLOC:
|
|
strncpy(pBuffer,
|
|
"Histogram memory out of memory!",
|
|
iBufLen);
|
|
break;
|
|
case HIST_BAD_CODE:
|
|
strncpy(pBuffer,
|
|
"Unknown or corrupted status code sent from master server",
|
|
iBufLen);
|
|
break;
|
|
case SEND_ERROR:
|
|
strncpy(pBuffer,
|
|
"Error sending data",
|
|
iBufLen);
|
|
break;
|
|
case CLOSE_ERROR:
|
|
strncpy(pBuffer,
|
|
"Error closing connection",
|
|
iBufLen);
|
|
break;
|
|
case INVALID_HARSH:
|
|
strncpy(pBuffer,
|
|
"Invalid parameter for harshness",
|
|
iBufLen);
|
|
break;
|
|
case SOFTWARE_ERROR:
|
|
strncpy(pBuffer,
|
|
"Internal error or software error at histogram memory computer, consult a hacker",
|
|
iBufLen);
|
|
break;
|
|
case DAQ_INHIBIT:
|
|
strncpy(pBuffer,
|
|
"Data aquisition inhibited by some client",
|
|
iBufLen);
|
|
break;
|
|
case DAQ_NOTSTOPPED:
|
|
strncpy(pBuffer,
|
|
"Data aquisition not stopped, suggests SW or network problem",
|
|
iBufLen);
|
|
break;
|
|
|
|
default:
|
|
strncpy(pBuffer,
|
|
"Unknown error code",iBufLen);
|
|
}
|
|
return 1;
|
|
}
|
|
/*-------------------------------------------------------------------------
|
|
SINQHM needs an additional top bin defining the upper edge of the
|
|
histogram. So, for a 512 bin array, 513 bins are needed. The additional
|
|
bin is created in the code below. This explains the strange arithmetic with
|
|
EdgeLength and the code at the end of the for loop
|
|
*/
|
|
int SINQHMDefineBank(pSINQHM self, int iBankNumber, int iStart, int iEnd,
|
|
float *iEdges, int iEdgeLength)
|
|
{
|
|
pSBank pWork = NULL;
|
|
int i, iDelay, iDiff;
|
|
|
|
assert(self);
|
|
assert(iBankNumber >= 0);
|
|
assert(iBankNumber < MAXBANK);
|
|
assert(iEdgeLength >= 2);
|
|
assert(iStart >= 0);
|
|
assert(iEnd >= iStart);
|
|
|
|
if(iBankNumber >= self->iBanks)
|
|
{
|
|
self->iBanks = iBankNumber +1;
|
|
}
|
|
pWork = &(self->pBank[iBankNumber]);
|
|
if(pWork->iEdges != NULL)
|
|
{
|
|
free(pWork->iEdges);
|
|
pWork->iEdges = NULL;
|
|
}
|
|
iDelay = (int)iEdges[0];
|
|
pWork->iStart = iStart;
|
|
pWork->iEnd = iEnd;
|
|
pWork->iEdgeLength = iEdgeLength;
|
|
if(iEdgeLength == 2)
|
|
{ /*
|
|
fixed binwidth: two values required: start stop in
|
|
edge[0], edge[1]
|
|
*/
|
|
pWork->iFlag = 0;
|
|
pWork->iDelay = iDelay;
|
|
pWork->iEdges = (unsigned int *)malloc(2*sizeof(unsigned int));
|
|
if(!pWork->iEdges)
|
|
{
|
|
return HIST_BAD_ALLOC;
|
|
}
|
|
pWork->iEdges[0] = htonl((unsigned int)iEdges[0]);
|
|
pWork->iEdges[1] = htonl((unsigned int)(iEdges[1] - iDelay));
|
|
return 1;
|
|
}
|
|
|
|
/*
|
|
normal case: create the bin boundaries
|
|
*/
|
|
pWork->iFlag = 1;
|
|
pWork->iEdgeLength++;
|
|
iEdgeLength++;
|
|
pWork->iEdges = (unsigned int *)malloc(iEdgeLength *
|
|
sizeof(unsigned int));
|
|
if(!pWork->iEdges)
|
|
{
|
|
return HIST_BAD_ALLOC;
|
|
}
|
|
pWork->iDelay = iDelay;
|
|
for(i = 0; i < iEdgeLength-1; i++)
|
|
{
|
|
pWork->iEdges[i] = htonl((unsigned int)(iEdges[i]-iDelay));
|
|
}
|
|
iDiff = iEdges[1] - iEdges[0];
|
|
pWork->iEdges[iEdgeLength-1] = htonl(iEdges[iEdgeLength-2]
|
|
+ iDiff - iDelay);
|
|
return 1;
|
|
}
|
|
/*-----------------------------------------------------------------------*/
|
|
struct tof {
|
|
uint n_extra_bytes;
|
|
usint n_edges;
|
|
usint n_banks;
|
|
uint preset_delay;
|
|
struct tof_edge_arr edge_0;
|
|
struct tof_bank bank_0;
|
|
};
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
int SINQHMTimeBin(pSINQHM self,int iMode)
|
|
{
|
|
int status, iRet;
|
|
struct req_buff_struct Req_buff;
|
|
struct rply_buff_struct Rply_buff;
|
|
int iLength, i, iDelay;
|
|
unsigned int iExtra;
|
|
char *pBuffer = NULL, *pPtr;
|
|
struct tof_edge_arr tea;
|
|
int iTeaLength;
|
|
struct tof_bank toba;
|
|
struct tof tofi;
|
|
|
|
assert(self);
|
|
|
|
/* figure out how long we are going to be*/
|
|
iLength = 24 + self->iBanks*sizeof(struct tof_bank);
|
|
for(i = 0; i < self->iBanks; i++)
|
|
{
|
|
iLength += 8 + self->pBank[i].iEdgeLength*sizeof(SQint32);
|
|
}
|
|
if(iLength < 64)
|
|
iLength = 64;
|
|
/* allocate send buffer */
|
|
pBuffer = (char *)malloc(iLength*sizeof(char));
|
|
if(!pBuffer)
|
|
{
|
|
return HIST_BAD_ALLOC;
|
|
}
|
|
memset(pBuffer,0,iLength);
|
|
|
|
/* do the message header */
|
|
iExtra = iLength - 64;
|
|
if(iExtra < 0)
|
|
iExtra = 0;
|
|
iDelay = self->pBank[0].iEdges[0];
|
|
Req_buff.bigend = htonl (0x12345678);
|
|
Req_buff.cmnd = htonl (SQHM_CONFIG);
|
|
Req_buff.u.cnfg.mode = htonl (iMode);
|
|
memcpy(pBuffer,&Req_buff,12);
|
|
pPtr = pBuffer + 12;
|
|
|
|
tofi.n_extra_bytes = htonl(iExtra);
|
|
tofi.n_edges = htons(self->iBanks);
|
|
tofi.n_banks = htons(self->iBanks);
|
|
tofi.preset_delay = htonl(self->pBank[0].iDelay);
|
|
memcpy(pPtr,&tofi,12);
|
|
pPtr += 12;
|
|
|
|
/* do the edge thingies */
|
|
for(i = 0; i < self->iBanks; i++)
|
|
{
|
|
tea.n_bins = htonl(self->pBank[i].iEdgeLength-1);
|
|
if(self->pBank[i].iEdgeLength == 2)
|
|
{
|
|
tea.flag = htonl(0);
|
|
}
|
|
else
|
|
{
|
|
tea.flag = htonl(1);
|
|
}
|
|
tea.edges = self->pBank[i].iEdges;
|
|
memcpy(pPtr,&tea,8);
|
|
pPtr += 8;
|
|
iTeaLength = self->pBank[i].iEdgeLength*4;
|
|
memcpy(pPtr,self->pBank[i].iEdges,iTeaLength);
|
|
pPtr += iTeaLength;
|
|
}
|
|
|
|
/* do the swiss bank structures */
|
|
for(i = 0; i < self->iBanks; i++)
|
|
{
|
|
toba.first = htons(self->pBank[i].iStart);
|
|
toba.n_cntrs = htons(self->pBank[i].iEnd);
|
|
toba.edge_indx = htons(i);
|
|
toba.bytes_per_bin = htons(self->iBinWidth);
|
|
memcpy(pPtr,&toba,sizeof(struct tof_bank));
|
|
pPtr += sizeof(struct tof_bank);
|
|
}
|
|
|
|
/* all packed up neat and nicely, send it */
|
|
/* try, get a connection to master server */
|
|
status = OpenMasterConnection(self);
|
|
if(status < 0)
|
|
{
|
|
if(pBuffer)
|
|
free(pBuffer);
|
|
return status;
|
|
}
|
|
|
|
/* send request */
|
|
status = send(self->iMasterSocket,pBuffer,iLength ,0);
|
|
if(pBuffer)
|
|
{
|
|
free(pBuffer);
|
|
}
|
|
if(status == -1)
|
|
{
|
|
return SEND_ERROR;
|
|
}
|
|
|
|
/* get a reply */
|
|
iRet = GetMasterReply(self,&Rply_buff,sizeof(Rply_buff));
|
|
if(iRet < 0)
|
|
{
|
|
/* try close the socket */
|
|
close(self->iMasterSocket);
|
|
self->iMasterSocket = 0;
|
|
return iRet;
|
|
}
|
|
else
|
|
{
|
|
/* close the socket */
|
|
status = close(self->iMasterSocket);
|
|
self->iMasterSocket = 0;
|
|
if((status != 0) && (errno != ECONNRESET))
|
|
{
|
|
return CLOSE_ERROR;
|
|
}
|
|
}
|
|
return 1; /* success, finally */
|
|
}
|