- Adding first working version of the McStas SICS connection to cvs

SKIPPED:
	psi/polterwrite.c
This commit is contained in:
koennecke
2005-06-22 07:09:59 +00:00
parent 734577e394
commit ef6c04e6b8
42 changed files with 3268 additions and 18 deletions

398
mccontrol.c Normal file
View File

@ -0,0 +1,398 @@
/*----------------------------------------------------------------------------
McStas simulation to SICS controller module mplementation file. For more details
see mcstas.tex.
copyright: see file COPYRIGHT
Mark Koennecke, June 2005
-----------------------------------------------------------------------------*/
#include <stdio.h>
#include <assert.h>
#include <tcl.h>
#include <time.h>
#include "stringdict.h"
#include "mccontrol.h"
/*========================= life and death ==================================*/
static void KillMcStasController(void *pData){
pMcStasController self = (pMcStasController)pData;
if(self == NULL){
return;
}
if(self->pDes != NULL){
DeleteDescriptor(self->pDes);
}
if(self->scripts != NULL){
DeleteStringDict(self->scripts);
}
free(self);
}
/*---------------------------------------------------------------------------*/
int McStasControllerFactory(SConnection *pCon, SicsInterp *pSics,
void *pData, int argc, char *argv[]){
pMcStasController pNew = NULL;
pNew = (pMcStasController)malloc(sizeof(McStasController));
if(pNew == NULL){
SCWrite(pCon,"ERROR: out of memory creating McStasController",
eError);
return 0;
}
memset(pNew,0,sizeof(McStasController));
pNew->pDes = CreateDescriptor("McStasController");
pNew->scripts = CreateStringDict();
if(pNew->pDes == NULL || pNew->scripts == NULL){
SCWrite(pCon,"ERROR: out of memory creating McStasController",
eError);
free(pNew);
return 0;
}
StringDictAddPair(pNew->scripts,"mcstart","UNDEFINED");
StringDictAddPair(pNew->scripts,"mcisrunning","UNDEFINED");
StringDictAddPair(pNew->scripts,"mcdump","UNDEFINED");
StringDictAddPair(pNew->scripts,"mckill","UNDEFINED");
StringDictAddPair(pNew->scripts,"mccopydata","UNDEFINED");
StringDictAddPair(pNew->scripts,"mcmonfile","UNDEFINED");
pNew->pid = -1;
return AddCommand(pSics,"mccontrol",
McStasControllerWrapper,
KillMcStasController,
pNew);
}
/*====================== interpreter interface ============================*/
static int configureController(pMcStasController self, SConnection *pCon,
int argc, char *argv[]){
char pBueffel[256];
if(argc < 4){
SCWrite(pCon,
"ERRROR: insufficient number of arguments to mccontrol configure",
eError);
return 0;
}
strtolower(argv[2]);
if(strcmp(argv[2],"update") == 0){
self->updateIntervall = atoi(argv[3]);
SCSendOK(pCon);
return 1;
}
if(!StringDictExists(self->scripts,argv[2])){
snprintf(pBueffel,255,"ERROR: scriptkey %s does not exist",argv[2]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
StringDictUpdate(self->scripts,argv[2],argv[3]);
SCSendOK(pCon);
return 1;
}
/*------------------------------------------------------------------------*/
static void listConfiguration(pMcStasController self, SConnection *pCon){
Tcl_DString txt;
char pLine[256];
char pScript[131];
Tcl_DStringInit(&txt);
StringDictGet(self->scripts,"mcstart",pScript,131);
snprintf(pLine,255,"mccontrol.mcstart = %s\n",pScript);
Tcl_DStringAppend(&txt,pLine,-1);
StringDictGet(self->scripts,"mcisrunning",pScript,131);
snprintf(pLine,255,"mccontrol.mcisrunning = %s\n",pScript);
Tcl_DStringAppend(&txt,pLine,-1);
StringDictGet(self->scripts,"mcdump",pScript,131);
snprintf(pLine,255,"mccontrol.mcdump = %s\n",pScript);
Tcl_DStringAppend(&txt,pLine,-1);
StringDictGet(self->scripts,"mckill",pScript,131);
snprintf(pLine,255,"mccontrol.mckill = %s\n",pScript);
Tcl_DStringAppend(&txt,pLine,-1);
StringDictGet(self->scripts,"mccopydata",pScript,131);
snprintf(pLine,255,"mccontrol.mccopydata = %s\n",pScript);
Tcl_DStringAppend(&txt,pLine,-1);
StringDictGet(self->scripts,"mcmonfile",pScript,131);
snprintf(pLine,255,"mccontrol.mcmonfile = %s\n",pScript);
Tcl_DStringAppend(&txt,pLine,-1);
snprintf(pLine,255,"mccontrol.updateintervall = %d\n",
self->updateIntervall);
Tcl_DStringAppend(&txt,pLine,-1);
snprintf(pLine,255,"mccontrol.pid = %d", self->pid);
Tcl_DStringAppend(&txt,pLine,-1);
SCWrite(pCon,Tcl_DStringValue(&txt),eValue);
Tcl_DStringFree(&txt);
}
/*--------------------------------------------------------------------------*/
static int invokeScript(pMcStasController self, char *name, SicsInterp *pSics,
char *result, int resultLen){
char pCommand[256], pScript[132], pMode[10];
Tcl_Interp *pTcl;
int status;
if(!StringDictGet(self->scripts,name,pScript,131)){
strncpy(result,"ERROR: script not found",resultLen);
return 0;
}
if(strcmp(name,"mccopydata") == 0){
snprintf(pCommand,255,"%s",pScript);
}else if(strcmp(name,"mcstart") == 0){
if(self->mode == eTimer){
strcpy(pMode,"timer");
}else {
strcpy(pMode,"monitor");
}
snprintf(pCommand,255,"%s %s %f", pScript,pMode,self->fPreset);
} else {
snprintf(pCommand,255,"%s %d",pScript,self->pid);
}
pTcl = InterpGetTcl(pSics);
status = Tcl_Eval(pTcl,pCommand);
strncpy(result, pTcl->result, resultLen);
if(status == TCL_OK){
return 1;
} else {
return 0;
}
}
/*------------------------------------------------------------------------*/
static int runScript(pMcStasController self, SConnection *pCon,
SicsInterp *pSics, int argc, char *argv[]){
char pResult[256];
int status;
if(argc < 3){
SCWrite(pCon,
"ERRROR: insufficient number of arguments to mccontrol run",
eError);
return 0;
}
status = invokeScript(self,argv[2],pSics,pResult,255);
if(status == 1){
SCWrite(pCon,pResult,eValue);
return 1;
} else {
SCWrite(pCon,pResult,eError);
return 0;
}
}
/*------------------------------------------------------------------------*/
static int start(pMcStasController self, SConnection *pCon){
int status;
status = McStasStart(self,eTimer,1000.);
if(status != OKOK){
SCWrite(pCon,self->errorText,eError);
return 0;
}
SCSendOK(pCon);
return 1;
}
/*-------------------------------------------------------------------------*/
int McStasControllerWrapper(SConnection *pCon, SicsInterp *pSics,
void *pData, int argc, char *argv[]){
pMcStasController self = NULL;
char pBueffel[255];
self = (pMcStasController)pData;
assert(self);
if(argc < 2) {
SCWrite(pCon,"ERROR: insufficient number of arguments to mccontrol",
eError);
return 0;
}
strtolower(argv[1]);
if(strcmp(argv[1],"configure") == 0){
return configureController(self,pCon,argc,argv);
} else if(strcmp(argv[1],"list") == 0){
listConfiguration(self,pCon);
return 1;
} else if(strcmp(argv[1],"run") == 0){
return runScript(self,pCon,pSics,argc,argv);
} else if(strcmp(argv[1],"start") == 0){
return start(self,pCon);
} else {
snprintf(pBueffel,255,"ERROR: subcommand %s to mccontrol unknown",
argv[1]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
return 0;
}
/*========================== the actual action functions =================*/
int McStasStart(pMcStasController self, CounterMode mode, float fPreset){
char pResult[256];
int status;
FILE *fd = NULL;
self->fPreset = fPreset;
self->mode = mode;
/**
* make sure that the monitor file has only a 0 in it...
*/
if(!StringDictGet(self->scripts,"mcmonfile",pResult,255)){
strncpy(self->errorText,"Misconfiguration: no monfile",255);
return HWFault;
}
fd = fopen(pResult,"w");
if(fd == NULL){
strncpy(self->errorText,"Failed to access monitor file",255);
return HWFault;
}
fprintf(fd,"0\n");
fclose(fd);
/*
* invoke start script
*/
status = invokeScript(self,"mcstart",pServ->pSics,pResult,255);
if(status == 0){
strncpy(self->errorText,pResult,255);
return HWFault;
}
/*
* some general initializations ..
*/
self->pid = atoi(pResult);
self->startTime = time(NULL);
self->lastUpdate = self->startTime - self->updateIntervall;
return OKOK;
}
/*------------------------------------------------------------------------*/
static long readMonFile(pMcStasController self){
char pResult[256];
FILE *fd = NULL;
long monValue = -1;
if(!StringDictGet(self->scripts,"mcmonfile",pResult,255)){
return -1;
}
fd = fopen(pResult,"r");
if(fd != NULL){
fscanf(fd,"%ld", &monValue);
fclose(fd);
}
return monValue;
}
/*------------------------------------------------------------------------*/
int McStasStatus(pMcStasController self, float *fControl){
char pResult[256];
long monValue;
int status, i;
status = invokeScript(self,"mcisrunning",pServ->pSics,pResult, 255);
if(status == 0){
strncpy(self->errorText,pResult,255);
return HWFault;
}
status = atoi(pResult);
/*
* handle timer mode
*/
if(status == 1 && self->mode == eTimer &&
time(NULL) >= self->startTime + (int)self->fPreset){
McStasStop(self);
return HWBusy;
} else {
*fControl = time(NULL) - self->startTime;
}
/*
* handle monitor mode
*/
if(status == 1 && self->mode == ePreset){
monValue = -1;
/*
* try to read the monfile up to three times. Problems reading it
* can be synchronisation problems with McStas
*/
for(i = 0, monValue = -1; i < 3; i++){
monValue = readMonFile(self);
if(monValue >= 0){
break;
}
}
if(monValue < 0){
strncpy(self->errorText,"Failed to read monitor file",255);
return HWFault;
}
*fControl = (float)monValue;
if(monValue >= (long)self->fPreset){
McStasStop(self);
}
}
if(status == 1){
return HWBusy;
} else {
self->stopTime = time(NULL);
self->pid = -1;
return HWIdle;
}
}
/*-------------------------------------------------------------------------*/
int McStasStop(pMcStasController self){
char pResult[256];
invokeScript(self,"mckill",pServ->pSics,pResult, 255);
self->lastUpdate = time(NULL) - 3*self->updateIntervall;
return 1;
}
/*-------------------------------------------------------------------------*/
int McStasTransferData(pMcStasController self){
char pResult[256];
int status;
/*
* prevent to frequent requests
*/
if(self->lastUpdate + self->updateIntervall > time(NULL)){
return OKOK;
}
if(self->pid >= 0){
status = invokeScript(self,"mcdump",pServ->pSics,pResult, 255);
if(status == 0){
strncpy(self->errorText,pResult,255);
return HWFault;
}
}
status = invokeScript(self,"mccopydata",pServ->pSics,pResult, 255);
if(status == 0){
strncpy(self->errorText,pResult,255);
return HWFault;
}
self->lastUpdate = time(NULL);
return OKOK;
}
/*-------------------------------------------------------------------------*/
int McStasGetError(pMcStasController self, char *error, int errLen){
strncpy(error,self->errorText,errLen);
return 1;
}
/*-------------------------------------------------------------------------*/
int McStasFix(pMcStasController self){
/*
* if the monitor file cannot be read, this may be caused by
* a conflict of mCstas writing while we are reading. let us
* retry...
*/
if(strstr(self->errorText,"monitor") != NULL){
return COREDO;
}
/*
* you have to edit the scripts to fix anything which is going wrong here.
* But make sure the simulation is stopped.
*/
McStasStop(self);
self->stopTime = time(NULL);
self->pid = -1;
return COTERM;
}
/*-------------------------------------------------------------------------*/
float McStasGetTime(pMcStasController self){
if(self->pid < 0){
return (float)(self->stopTime - self->startTime);
} else {
return (float)time(NULL) - self->startTime;
}
}