Index: /trunk/FACT++/src/EventBuilder.c
===================================================================
--- /trunk/FACT++/src/EventBuilder.c	(revision 10962)
+++ /trunk/FACT++/src/EventBuilder.c	(revision 10963)
@@ -1,4 +1,6 @@
 
 
+#define PX8   99  //simulator does not create double-length roi for pixel 8  
+                  //for real data, set PX8 = 8 ==> ask for double roi=TM
 
 
@@ -6,4 +8,5 @@
 #include <stdlib.h>
 #include <stdint.h>
+#include <unistd.h>
 #include <stdio.h>
 #include <time.h>
@@ -19,15 +22,40 @@
 #include <sched.h>
 
-
 #include "EventBuilder.h"
 
-#define ETHTEST   0
+enum Severity
+{
+        kMessage = 10, ///< Just a message, usually obsolete
+        kInfo    = 20, ///< An info telling something which can be interesting to know
+        kWarn    = 30, ///< A warning, things that somehow might result in unexpected or unwanted bahaviour
+        kError   = 40, ///< Error, something unexpected happened, but can still be handled by the program
+        kFatal   = 50, ///< An error which cannot be handled at all happend, the only solution is program termination
+        kDebug   = 99, ///< A message used for debugging only
+};
+
 #define MIN_LEN  32        // min #bytes needed to interpret FADheader
 #define MAX_LEN  64*1024   // size of read-buffer per socket
    
+extern FileHandle_t  runOpen(uint32_t irun, RUN_HEAD *runhd, size_t len ) ;
+extern int  runWrite(FileHandle_t fileHd ,  EVENT    *event, size_t len ) ;
+extern int  runClose(FileHandle_t fileHd ,  RUN_TAIL *runth, size_t len ) ;
+extern void factOut(int severity, int err, char* message ) ;
+extern void factStat(int severity, int err, char* message ) ;
+
 int g_actTime   =  0 ;
 int g_runStat   = 40 ;
-int g_actBoards = 20 ;
-
+int g_actBoards = 40 ;
+size_t g_maxMem  ;  //maximum memory allowed for buffer
+
+int     g_maxBoards ;    //maximum number of boards to be initialized
+FACT_SOCK g_port[NBOARDS] ;  // .addr=string of IP-addr in dotted-decimal "ddd.ddd.ddd.ddd"
+
+
+int gi_runStat ;
+int gp_runStat ;
+int gw_runStat ;
+
+
+int  gi_maxSocks = 0 ;  
 uint gi_SecRate[MAX_SOCK] ;
 uint gi_S10Rate[MAX_SOCK] ;
@@ -42,7 +70,10 @@
 uint gi_EvtBad  = 0 ;
 uint gi_EvtTot  = 0 ;
+size_t gi_usedMem = 0 ;
+
 uint gw_EvtTot  = 0 ;
 uint gp_EvtTot  = 0 ;
 
+PIX_MAP g_pixMap[NPIX] ;
 
 EVT_CTRL    evtCtrl ;       //control of events during processing
@@ -78,5 +109,5 @@
   int32_t  bufLen ;          //number of bytes left to read
 
-  int  sockStat   ;      //-1 if socket not yet connected
+  int  sockStat   ;      //-1 if socket not yet connected  , 99 if not exist
   int  socket     ;      //contains the sockets
   struct sockaddr_in SockAddr ; //IP for each socket
@@ -84,5 +115,4 @@
   int  evtID  ;          // event ID of event currently read
   int  runID  ;          // run       "
-//int  evtPtr ;          // index into evtCtrl structure
   uint  fadLen ;          // FADlength of event currently read
   int  fadVers ;         // Version of FAD
@@ -90,5 +120,4 @@
   int  Port ;
 
-//  int8_t *rBuf;          //local buffer to be used when no event defined yet
   CNV_FACT *rBuf ;
 
@@ -102,7 +131,6 @@
 
 
-
-struct timespec xwait ;
-
+#define MXSTR 1000 
+char str[MXSTR] ;
 
 SHORT_BYTE  start, stop;
@@ -119,5 +147,5 @@
 
 
-int GenSock(int flag, int crate0, int board0, int port0, READ_STRUCT *rd) {
+int GenSock(int flag, int port, struct sockaddr_in *sockAddr,  READ_STRUCT *rd) {
 /*
 *** generate Address, create sockets and allocates readbuffer for it
@@ -126,14 +154,6 @@
  */
 
-  int crate, board, port ;
-  char IPstr[100] ;
-  struct in_addr IPaddr ;
 
   rd->sockStat = -1 ;
-
-
-  crate = crate0;
-  board = board0;
-  port  = port0 ;
 
 
@@ -141,5 +161,6 @@
      close(rd->socket) ;
      if ( (rd->socket = socket (PF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0)) <= 0) {
-        error(1,errno,"Could not generate socket\n");
+        snprintf(str,MXSTR,"Could not generate socket | %m");
+        factOut(kFatal,771, str ) ;
         return -2 ;
      }
@@ -147,140 +168,26 @@
   }
 
-
-  if (ETHTEST >0) {
-     port = port0+100*crate0+10*board0 ;
-     sprintf(IPstr,"10.0.%d.11",128+crate); // test on fact1
-//      if (board==3) sprintf(IPstr,"10.0.100.11");
-
-//     sprintf(IPstr,"10.0.131.11"); // test on fact1
-     inet_pton(PF_INET, IPstr, &IPaddr) ;
-     port = port0+100*crate0+10*board0 ;
-  } else {
-
-
-     sprintf(IPstr,"10.0.%d.%d",128+crate,128+board); // real environment
-     if ( inet_pton(PF_INET, IPstr, &IPaddr) <=0 ) {
-        error(1,errno,"Error: bad address c=%d b=%d '%s'\n", crate, board, IPstr);
-        return -1 ;
-     }
-  } 
-
      rd->Port  = port ;
-     rd->board = crate0*10+board0 ;
-     rd->SockAddr.sin_family = PF_INET;
+     rd->SockAddr.sin_family = sockAddr->sin_family;
      rd->SockAddr.sin_port = htons(port) ;
-     rd->SockAddr.sin_addr = IPaddr ;
+     rd->SockAddr.sin_addr = sockAddr->sin_addr ;
 
      if ( (rd->socket = socket (PF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0)) <= 0) {
-        error(1,errno,"Could not generate socket\n");
+        snprintf(str,MXSTR,"Could not generate socket | %m");
+        factOut(kFatal,773, str ) ;
         return -2 ;
      } else {
        rd->rBuf = malloc(sizeof(CNV_FACT) ) ;
        if ( rd->rBuf == NULL ) {
-          error(1,errno,"Could not create local buffer\n");
+          snprintf(str,MXSTR,"Could not create local buffer");
+          factOut(kFatal,774, str ) ;
           return -3 ;
        }
      }
-
   return 0 ;
 
 } /*-----------------------------------------------------------------*/
 
-
-int PrintErr() {
-
-  int k,c,b,p,s ;
-
-
-       k=0 ;
-       printf("Errors:\n");
-       for (c=0; c<4; c++) {
-          for (b=0; b<10; b++) {
-             s=0 ;
-             printf("c%d b%d: ",c,b);
-             for (p=1; p<8; p++) {
-                printf("%7d",gi_ErrCnt[k]);
-                s+=gi_ErrCnt[k];
-             }
-             printf("%8d\n",s);
-          }
-       }
-
-       return 0;
-} /*-----------------------------------------------------------------*/
-
-
-int PrintRate() {
-
-  int k,c,b,p,s ;
-
-
-    if (g_actTime > gi_SecTime) {
-       gi_SecTime = g_actTime ;
-       printf("Nr Ev start %d compl %d bad %d\n",gi_EvtStart,gi_EvtRead,gi_EvtBad) ;
-
-
-       k=0 ;
-       printf("Rate/Second:\n");
-       for (c=0; c<4; c++) {
-          for (b=0; b<10; b++) {
-             s=0 ;
-             printf("c%d b%d: ",c,b);
-             for (p=1; p<8; p++) {
-                printf("%7d",gi_SecRate[k]);
-                s+=            gi_SecRate[k];
-                gi_S10Rate[k]+=gi_SecRate[k];
-                gi_SecRate[k++]=0 ;
-             }
-             printf("%8d\n",s);
-          }
-       }
-       for (b=0; b<NBOARDS; b++)
-          printf("%d ",gi_NumConnect[b]) ;
-       printf("\n");
-    }
-
-
-    if ( g_actTime%10 == 0 && g_actTime > gi_S10Time) {
-       gi_S10Time = g_actTime ;
-       k=0 ;
-       printf("Rate/10Second:\n");
-       for (c=0; c<4; c++) {
-          for (b=0; b<10; b++) {
-             s=0 ;
-             printf("c%d b%d: ",c,b);
-             for (p=1; p<8; p++) {
-                printf("%7d",gi_S10Rate[k]);
-                s+=            gi_S10Rate[k];
-                gi_MinRate[k]+=gi_S10Rate[k];
-                gi_S10Rate[k++]=0 ;
-             }
-             printf("%8d\n",s);
-          }
-       }
-    }
-
-
-    if ( g_actTime%60 == 0 && g_actTime > gi_MinTime) {
-       gi_MinTime = g_actTime ;
-       k=0 ;
-       printf("Rate/Minute:\n");
-       for (c=0; c<4; c++) {
-          for (b=0; b<10; b++) {
-             printf("c%d b%d: ",c,b);
-             s=0 ;
-             for (p=1; p<8; p++) {
-                printf("%7d",gi_MinRate[k]);
-                s+=          gi_MinRate[k];
-                gi_MinRate[k++]=0 ;
-             }
-             printf("%8d\n",s);
-          }
-       }
-    }
-  
-      return 0;
-
-} /*-----------------------------------------------------------------*/
+  /*-----------------------------------------------------------------*/
 
 
@@ -290,5 +197,8 @@
 // initialize mBuffer (mark all entries as unused\empty)
 
-   int i,j,k ;
+   int i ;
+   uint32_t actime ;
+
+   actime = g_actTime + 50000000 ;
 
    for (i=0; i<MAX_EVT*MAX_RUN; i++) {
@@ -297,25 +207,13 @@
       evtCtrl.evtBuf[  i] = -1 ;
       evtCtrl.evtStat[ i] = -1 ;
-      evtCtrl.pcTime[  i] = g_actTime + 50000000 ;  //initiate to far future
-   }
-
-   for (i=0; i<MAX_RUN; i++) {
-      runCtrl[i].runId = 
-      runCtrl[i].lastTime = 
-      runCtrl[i].nextEvt = 0 ;
-      runCtrl[i].fileId = -2 ;
-
-      for (k=0; k<MAX_EVT; k++) runCtrl[i].buffId[k] = 0 ;
-
-      runTail[i].nEventsOk =
-      runTail[i].nEventsRej =
-      runTail[i].nEventsBad =
-      runTail[i].PCtime0 =
-      runTail[i].PCtimeX = 0 ;
-   }
-
-
-   evtCtrl.readPtr =  0 ;
-   evtCtrl.writePtr=  0 ;
+      evtCtrl.pcTime[  i] = actime ;  //initiate to far future
+
+   }
+
+
+   actRun.FADhead = malloc( NBOARDS* sizeof(PEVNT_HEADER) ) ;
+
+   evtCtrl.frstPtr = 0 ;
+   evtCtrl.lastPtr = 0 ;
 
    return 0 ;
@@ -326,5 +224,5 @@
 
 
-int mBufEvt(int evID, int runID, int nRoi) {
+int mBufEvt(uint evID, uint runID, uint nRoi) {
 // generate a new Event into mBuffer:   
 // make sure only complete Event are possible, so 'free' will always work
@@ -333,7 +231,10 @@
 
    int i, k, evFree ;
-
-   if (nRoi < 0 || nRoi > 1024) {
-      printf("illegal nRoi %d\n",nRoi) ;
+   int headmem=0 ;
+   size_t needmem = 0 ;
+
+   if (nRoi <=0 || nRoi > 1024) {
+      snprintf(str,MXSTR,"illegal nRoi: %d",nRoi) ;
+      factOut(kError, 1, str ) ;
       return 99 ;
    }
@@ -354,71 +255,47 @@
    //event does not yet exist; create
    if (evFree < 0 ) {        //no space available in ctrl
-        error(0,0, "no space left to keep event...") ;
+        snprintf(str,MXSTR,"no control slot to keep event...") ;
+        factOut(kError,881, str ) ;
         return -1 ;
    }
+   i = evFree ;   //found free entry; use it ...
 
    
-
-   i = evFree ;   //found free entry; use it ...
-
-   mBuffer[i].fEvent  = malloc( sizeof(EVENT) ) ;
-   if (mBuffer[i].fEvent  == NULL) return -12;
-
-
-   mBuffer[i].fEvent->StartPix  = malloc( NPIX * sizeof(int16_t) ) ;
-   if (mBuffer[i].fEvent->StartPix  == NULL) {
+   needmem = sizeof(EVENT) + NPIX*nRoi*2 + NTMARK*nRoi*2 - 2 ; //-2 because of dummy adc_data[1]
+
+   headmem = NBOARDS* sizeof(PEVNT_HEADER) ;
+
+   if ( gi_usedMem + needmem + headmem > g_maxMem) {
+        snprintf(str,MXSTR,"no memory left to keep event...") ;
+        factOut(kError,882, str ) ;
+        return -1 ;
+   }
+
+   mBuffer[i].FADhead = malloc( headmem ) ;
+   if (mBuffer[i].FADhead == NULL) {
+      return -12;
+   }
+
+   mBuffer[i].fEvent  = malloc( needmem ) ;
+   if (mBuffer[i].fEvent  == NULL) {
       free(mBuffer[i].fEvent) ;
       mBuffer[i].fEvent = NULL ;
-      mBuffer[i].nRoi = -3 ;
-      return -13;
-   }
-   for (k=0; k<NPIX; k++) mBuffer[i].fEvent->StartPix[k] = -1 ;
-
-   mBuffer[i].fEvent->StartTM   = malloc( NTMARK * sizeof(int16_t) ) ;
-   if (mBuffer[i].fEvent->StartTM  == NULL) {
-      free(mBuffer[i].fEvent->StartPix ) ;
-      free(mBuffer[i].fEvent) ;
-      mBuffer[i].fEvent = NULL ;
-      mBuffer[i].nRoi = -4 ;
-      return -14;
-   }
-   for (k=0; k<NTMARK; k++) mBuffer[i].fEvent->StartTM[k] = -1 ;
-
-   mBuffer[i].fEvent->Adc_Data = malloc( NPIX  * nRoi * sizeof(int16_t) ) ;
-   if (mBuffer[i].fEvent->Adc_Data == NULL) {
-      free(mBuffer[i].fEvent->StartTM  ) ;
-      free(mBuffer[i].fEvent->StartPix ) ;
-      free(mBuffer[i].fEvent) ;
-      mBuffer[i].fEvent = NULL ;
-      mBuffer[i].nRoi = -5 ;
-      return -15;
-   }
-
-   mBuffer[i].fEvent->Adc_Tmark= malloc( NTMARK* nRoi * sizeof(int16_t) ) ;
-   if (mBuffer[i].fEvent->Adc_Tmark== NULL) {
-      free(mBuffer[i].fEvent->Adc_Data ) ;
-      free(mBuffer[i].fEvent->StartTM  ) ;
-      free(mBuffer[i].fEvent->StartPix ) ;
-      free(mBuffer[i].fEvent) ;
-      mBuffer[i].fEvent = NULL ;
-      mBuffer[i].nRoi = -6 ;
-      return -16;
-   }
-
-   mBuffer[i].fEvent->FADhead = malloc( NBOARDS* sizeof(PEVNT_HEADER) ) ;
-   if (mBuffer[i].fEvent->FADhead== NULL) {
-      free(mBuffer[i].fEvent->Adc_Tmark ) ;
-      free(mBuffer[i].fEvent->Adc_Data ) ;
-      free(mBuffer[i].fEvent->StartTM  ) ;
-      free(mBuffer[i].fEvent->StartPix ) ;
-      free(mBuffer[i].fEvent) ;
-      mBuffer[i].fEvent = NULL ;
-      mBuffer[i].nRoi = -7 ;
-      return -17;
-   }
-
+      return -22;
+   }
+
+   //flag all boards as unused
    mBuffer[i].nBoard = 0 ;
    for (k=0; k<NBOARDS; k++ ) {
       mBuffer[i].board[k] = -1;
+   }
+
+   //flag all pixels as unused
+   for (k=0; k<NPIX; k++ ) {
+      mBuffer[i].fEvent->StartPix[k] = -1 ;
+   }
+
+   //flag all TMark as unused
+   for (k=0; k<NTMARK; k++ ) {
+      mBuffer[i].fEvent->StartTM[k] = -1 ;
    }
 
@@ -427,15 +304,21 @@
    mBuffer[i].evNum   = evID  ;
    mBuffer[i].runNum  = runID ;
-
+   mBuffer[i].evtLen  = needmem ;
+
+   gi_usedMem += needmem + headmem;
 
    //register event in 'active list (reading)'
 
-   evtCtrl.evtBuf[  evtCtrl.readPtr] = i ;
-   evtCtrl.evtStat[ evtCtrl.readPtr] = 0 ;
-   evtCtrl.pcTime[  evtCtrl.readPtr] = g_actTime ;
-   evtIdx[i] = evtCtrl.readPtr ;
-
-   evtCtrl.readPtr++ ;
-   if (evtCtrl.readPtr == MAX_EVT*MAX_RUN ) evtCtrl.readPtr = 0;
+   evtCtrl.evtBuf[  evtCtrl.lastPtr] = i ;
+   evtCtrl.evtStat[ evtCtrl.lastPtr] = 0 ;
+   evtCtrl.pcTime[  evtCtrl.lastPtr] = g_actTime ;
+   evtIdx[i] = evtCtrl.lastPtr ;
+snprintf(str,MXSTR,"%5d start new evt  %8d %8d %2d",evID,i,evtCtrl.lastPtr,0);
+factOut(kDebug,-11, str ) ;
+   evtCtrl.lastPtr++ ;
+   if (evtCtrl.lastPtr == MAX_EVT*MAX_RUN ) evtCtrl.lastPtr = 0;
+
+
+
 
    gi_EvtStart++ ;
@@ -449,9 +332,9 @@
    
    if (evFree <0 ) {
-      error(0,0, "not able to register the new run %d\n",runID);
+      snprintf(str,MXSTR,"not able to register the new run %d",runID);
+      factOut(kError,883, str ) ;
    } else {
       runCtrl[evFree].runId = runID ;
    }
-
 
    return i ;
@@ -464,14 +347,22 @@
 //(and make sure multiple calls do no harm ....)
 
+   int headmem=0 ;
+   size_t freemem = 0 ;
+
    if ( mBuffer[i].nRoi > 0) {      //have an fEvent structure generated ...
-      free(mBuffer[i].fEvent->Adc_Tmark) ;
-      free(mBuffer[i].fEvent->Adc_Data ) ;
-      free(mBuffer[i].fEvent->StartTM  ) ;
-      free(mBuffer[i].fEvent->StartPix ) ;
+      freemem = mBuffer[i].evtLen ; 
       free(mBuffer[i].fEvent ) ;
       mBuffer[i].fEvent = NULL ;
-   }
+
+      free(mBuffer[i].FADhead ) ;
+      mBuffer[i].FADhead = NULL ;
+
+   }
+   headmem = NBOARDS* sizeof(PEVNT_HEADER) ;
    mBuffer[i].evNum   = mBuffer[i].runNum = mBuffer[i].nRoi= -1;
-    
+
+   gi_usedMem = gi_usedMem - freemem - headmem;
+
+
    return 0 ;
  
@@ -483,22 +374,76 @@
 
 
-int initReadFAD() {
-/* *** initialize reading of FAD data */
-  int32_t i,j,k ;
-  int c,b,p ;
-
+void initReadFAD() {
+return ;
+} /*-----------------------------------------------------------------*/
+
+
+
+void *readFAD( void *ptr ) {
+/* *** main loop reading FAD data and sorting them to complete events */
+  int head_len,frst_len,numok,numok2,dest,evID,i,j,k ;
+  int32_t jrd ;
+  int32_t myRun ;
+  int boardId, roi,drs,px,src,pixS,pixH,pixC,pixR,tmS ;
+  uint qtot = 0, qread = 0, qconn = 0 ;
+  int errcnt0 = 0 ;
+
+  int goodhed=0;
+
+  struct timespec xwait ;
+
+  int nokCnt[MAX_SOCK],loopCnt=0;
+  int sokCnt[MAX_SOCK];
+
+
+  snprintf(str,MXSTR,"start initializing");
+  factOut(kInfo,-1, str ) ;
+
+  int cpu = 7 ;   //read thread
+  cpu_set_t mask;
+
+/* CPU_ZERO initializes all the bits in the mask to zero. */
+   CPU_ZERO( &mask );
+/* CPU_SET sets only the bit corresponding to cpu. */
+   cpu = 7 ;
+   CPU_SET( cpu, &mask );
+// cpu = 6 ;
+// CPU_SET( cpu, &mask );
+
+/* sched_setaffinity returns 0 in success */
+   if ( sched_setaffinity( 0, sizeof(mask), &mask ) == -1 ) {
+      snprintf(str,MXSTR,"W ---> can not create affinity to %d",cpu);
+      factOut(kWarn,-1, str ) ;
+   }
+
+
+  gi_maxSocks = 0 ;
+
+  //make sure all sockets are preallocated as 'not exist'
+  for (i=0; i<MAX_SOCK; i++) {
+     rd[i].socket   = -1 ; 
+     rd[i].sockStat = 99 ;
+  }
+
+  int b,p,p0 ;
+  k = 0 ;
+  for (b=0; b<NBOARDS; b++ ) {
+     if ( g_port[b].sockDef >=0 ) {
+        p0=ntohs(g_port[b].sockAddr.sin_port);
+        for (p=p0+1; p<p0+8; p++) {
+           j = GenSock(0,p, &g_port[b].sockAddr, &rd[k]) ;
+           if ( j != 0 ) {
+              snprintf(str,MXSTR,"problem with Address board %d port %d",b,p);
+              factOut(kFatal,101, str ) ;
+           } else {
+              rd[k].board = b ;
+              k++ ;
+              gi_maxSocks++ ;
+           }
+        }
+     }
+  }
 
   g_actTime = time(NULL) ;
-
-  k = 0 ;
-  for ( c=0; c<4; c++ )
-     for (b=0; b<10; b++ )
-        for (p=5001; p<5008; p++) {
-          j = GenSock(0,c,b,p, &rd[k]) ;
-          if ( j != 0 ) printf("problem with c%d b%d p%d\n",c,b,p);
-//        else          printf("ok socket %d = %d\n",k,rd[k].socket) ;
-          k++ ;
-        }
-
   for (k=0; k<MAX_SOCK; k++)
      gi_SecRate[k]=gi_S10Rate[k]=gi_MinRate[k]=gi_ErrCnt[k] = 0 ;
@@ -509,36 +454,17 @@
 
   gi_SecTime= gi_S10Time= gi_MinTime= g_actTime ;
-     
-         return NULL;
-
-} /*-----------------------------------------------------------------*/
-
-
-
-void *readFAD( void *ptr ) {
-/* *** main loop reading FAD data and sorting them to complete events */
-  int head_len,frst_len,numok,numok2,evFree,dest,evID,i,j,k ;
-  int32_t jrd ;
-  int8_t FADbyte0, FADbyte1, FADbyteX0, FADbyteX1 ;
-  int32_t myRun, cleanTime ;
-  int boardId, roi,drs,px,src,pixS,pixH,pixC,pixR,tmS ;
-  int reqBoards = 40 ;
-
-  int goodevt=0;
-  int goodhed=0;
-  int nbuf=0;
-  int ret ;
-
-  int waitTime = 10 ; //maximum nr of seconds wait for delayed packets
-
-  int nokCnt[MAX_SOCK],loopCnt=0;
-  int sokCnt[MAX_SOCK];
+
+
+
+  mBufInit() ;    //initialize buffers
+
+  snprintf(str,MXSTR,"end   initializing");
+  factOut(kInfo,-1, str ) ;
+
 
   for (k=0; k<MAX_SOCK; k++) sokCnt[k]=nokCnt[k]=0 ;
 
-
   head_len = sizeof(PEVNT_HEADER) ;
-  frst_len = head_len + 36 * 12 ;
-  if (head_len < MIN_LEN) { printf("headLen ...\n"); exit(99);}
+  frst_len = head_len + 36 * 12 ;   //fad_header plus 36*pix_header
 
   numok = numok2   = 0 ;
@@ -548,14 +474,11 @@
 
   myRun = g_actTime ;
-  cleanTime = g_actTime ;     //once per second cleanup buffers from too old data
-
-
-
-
-  mBufInit() ;
-
-
-  while (g_runStat > 0) {           //loop until global variable g_stop is set
-
+
+  gi_runStat = g_runStat ;
+
+
+  while (g_runStat >=0) {           //loop until global variable g_stop is set
+
+    gi_runStat = g_runStat ;
 
     g_actTime = time(NULL) ;
@@ -566,19 +489,20 @@
     numok = 0 ;                       //count number of succesfull actions
 
-    for (i=0; i<MAX_SOCK; i++) {      //check all sockets if something to read
-
+    for (i=0; i<gi_maxSocks; i++) {      //check all sockets if something to read
       if (rd[i].sockStat <0 ) {         //try to connect if not yet done
         rd[i].sockStat=connect(rd[i].socket,
             (struct sockaddr*) &rd[i].SockAddr, sizeof(rd[i].SockAddr)) ;
-        if (rd[i].sockStat >=0 ) {      //successfull ==>
+        if (rd[i].sockStat ==0 ) {      //successfull ==>
           rd[i].bufTyp = 0 ;            //  expect a header
           rd[i].bufLen = frst_len ;     //  max size to read at begining
           rd[i].bufPos = 0 ;            //  no byte read so far
- gi_NumConnect[ rd[i].board ]++ ;
- printf("+++connect %d %d\n",rd[i].board,gi_NumConnect[ rd[i].board ]);
+          gi_NumConnect[ rd[i].board ]++ ;
+          numok++ ;                     //make sure next round will execute
+          snprintf(str,MXSTR,"+++connect %d %d",rd[i].board,gi_NumConnect[ rd[i].board ]);
+          factOut(kInfo,-1, str ) ;
         }
       }
 
-      if (rd[i].sockStat >=0) {     //we have a connection ==> try to read
+      if (rd[i].sockStat ==0) {     //we have a connection ==> try to read
         numok++ ;
         sokCnt[i]++;
@@ -587,19 +511,19 @@
         if (jrd == 0) {                 //connection has closed ...
            rd[i].sockStat = -1 ;        //flag (try to reopen next round)
-           error(0,errno,"Socket %d closed",i);
-           j = GenSock(1,0,0,0, &rd[i]) ;
+           snprintf(str,MXSTR,"Socket %d closed by FAD",i);
+           factOut(kInfo,441, str ) ;
+           j = GenSock(1,0,NULL, &rd[i]) ;
            gi_ErrCnt[i]++ ;
- gi_NumConnect[ rd[i].board ]-- ;
- printf("disconnect %d %d\n",rd[i].board,gi_NumConnect[ rd[i].board ]);
+           gi_NumConnect[ rd[i].board ]-- ;
         } else if ( jrd<0 ) {           //did not read anything
            if (errno != EAGAIN && errno != EWOULDBLOCK ) {
-              error(1,errno,"Error Reading from %d",i);
+              snprintf(str,MXSTR,"Error Reading from %d | %m",i);
+              factOut(kError,442, str ) ;
               gi_ErrCnt[i]++ ;
            } else  numok-- ;            //else nothing waiting to be read
 
         } else if ( rd[i].bufTyp >0 ) { // we are reading data ...
-//printf("received data %d %d\n", i,jrd);
-
-            if ( jrd < rd[i].bufLen ) {    //not yet all read
+           qread+=jrd ;
+           if ( jrd < rd[i].bufLen ) {    //not yet all read
              rd[i].bufPos += jrd ;        //==> prepare for continuation
              rd[i].bufLen -= jrd ;
@@ -610,6 +534,6 @@
                && rd[i].rBuf->B[ rd[i].bufPos  ] != stop.B[1]) {
                 gi_ErrCnt[i]++ ;
-                printf( "wrong end of buffer found %d\n",rd[i].bufPos);
- exit(1) ;
+                snprintf(str,MXSTR,"wrong end of buffer found %d",rd[i].bufPos);
+                factOut(kError,301, str ) ;
                 goto EndBuf ;
 
@@ -624,7 +548,7 @@
 
              if (evID < 0) {
-                printf("no space left ...%d\n",evID) ;
- exit(2) ;
-                goto EndBuf ;
+                snprintf(str,MXSTR,"no space left ...%d",evID) ;
+                factOut(kError,201, str ) ;
+                goto EndBuf ; //--> skip event (and hope it will improve)
              } 
 
@@ -632,64 +556,78 @@
 
              boardId = rd[i].board  ;
-             if ( mBuffer[evID].board[ boardId ] != -1) {   //this board already stored ...
-                printf( "board of this event already stored ...") ;
-             } else {
-
-                int iDx = evtIdx[evID] ;   //index into evtCtrl
-
-                memcpy( &mBuffer[evID].fEvent->FADhead[boardId].start_package_flag,
+             int fadBoard = ntohs(rd[i].rBuf->S[12] ) ;
+             int fadCrate = fadBoard/256 ;
+             if (boardId != (fadCrate*10 + fadBoard%256) ) {
+                snprintf(str,MXSTR,"wrong Board ID %d %d %d",fadCrate,fadBoard%256,boardId) ;
+                if (errcnt0++ < 99 ) factOut(kWarn,301, str ) ;  //print only few times
+//           } else {
+//              snprintf(str,MXSTR,"correct Board ID %d %d %d",fadCrate,fadBoard%256,boardId) ;
+//              if (errcnt0++ < 99 ) factOut(kWarn,301, str ) ;  //print only few times
+             }
+             if ( mBuffer[evID].board[ boardId ] != -1) {   
+                snprintf(str,MXSTR,"double board %d for event %d",boardId,evID) ;
+                factOut(kWarn,501, str ) ;
+                goto EndBuf ; //--> skip Board
+             } 
+
+             int iDx = evtIdx[evID] ;   //index into evtCtrl
+
+             memcpy( &mBuffer[evID].FADhead[boardId].start_package_flag,
                         &rd[i].rBuf->S[0], head_len) ;
-                mBuffer[evID].board[ boardId ] = boardId ;
-                roi  = mBuffer[evID].nRoi ;
-
-                pixS = boardId*36 -1 ;   //
-                tmS  = boardId*4  -1 ;   //
-                src  = head_len/2 ;
-                for ( drs=0; drs<4; drs++ ) {
-                   for ( px=0; px<9; px++ ) {
-                      pixH= ntohs(rd[i].rBuf->S[src++]) ;
-                      pixC= ntohs(rd[i].rBuf->S[src++]) ;
-                      pixR= ntohs(rd[i].rBuf->S[src++]) ;
- 
-                      src++  ;
-                      pixS++ ; //pixS = pixH2S[pixH] ;
-                      if (pixR != roi ) {
-                         if (px == 8 && pixR == 2*roi ) {
-                         } else {
-                            printf("wrong roi %d %d %d %d\n",px,pixR,roi,src-2);
-//exit(66);
-                         }
-//                         goto EndBuf ;
-                      }
-
+             roi  = mBuffer[evID].nRoi ;
+
+             pixS = boardId*36 -1 ;   //
+             tmS  = boardId*4  -1 ;   //
+             src  = head_len/2 ;
+             for ( drs=0; drs<4; drs++ ) {
+                for ( px=0; px<9; px++ ) {
+                   pixH= ntohs(rd[i].rBuf->S[src++]) ;
+                   pixC= ntohs(rd[i].rBuf->S[src++]) ;
+                   pixR= ntohs(rd[i].rBuf->S[src++]) ;
+
+                   src++  ;
+                   pixS++ ; //pixS = pixH2S[pixH] ;
+                   if ( ( px < PX8 && pixR == roi )
+                     || ( px ==PX8 && pixR == 2*roi )
+                     || ( px ==PX8 && pixR == roi && roi > 512 ) ) {
+                       // correct roi
                       mBuffer[evID].fEvent->StartPix[pixS] =pixC;
                       dest= pixS * roi ;
                       memcpy(
-                            &mBuffer[evID].fEvent->Adc_Data[dest],
-                            &rd[i].rBuf->S[src],  roi * 2) ;
+                           &mBuffer[evID].fEvent->Adc_Data[dest],
+                           &rd[i].rBuf->S[src],  roi * 2) ;
                       src+= roi ;
-
-        //            if (px==8 && roi < 512 ) {
-        //               tmS++ ;
-        //               dest= tmS * roi ;
-        //               mBuffer[evID].fEvent->StartTM[pixS] =pixC+roi;
-        //               memcpy(
-        //                     &mBuffer[evID].fEvent->Adc_Tmark[dest],
-        //                     &rd[i].rBuf.S[src],  roi * 2) ;
-// ?? not in the simulator ...                      src+= roi ;
-        //            }
+                      if ( px==PX8 ) {
+                         tmS++; // tmS = tmH2S[pixH]
+                         dest= tmS * roi + NPIX* roi ;
+                         if ( roi <=512 ) {
+                            mBuffer[evID].fEvent->StartTM[tmS] =(pixC+roi)%1024 ;
+                            memcpy(
+                              &mBuffer[evID].fEvent->Adc_Data[dest],
+                              &rd[i].rBuf->S[src],  roi * 2) ;
+                            src+=roi ;
+                         } else {
+                             mBuffer[evID].fEvent->StartTM[tmS] = -1 ;
+                         }
+                      }
+                   } else {
+                      snprintf(str,MXSTR,"wrong roi %d %d %d %d",px,pixR,roi,src-2);
+                      factOut(kError,202, str ) ;
+                      goto EndBuf ;
                    }
                 }
-                evtCtrl.evtStat[ iDx ]++ ;
-                evtCtrl.pcTime[ iDx ] = g_actTime ;
-
-                if (++mBuffer[evID].nBoard == 19 ) {
-                   //complete event read ---> flag for next processing
-                   evtCtrl.evtStat[ iDx ] = 99;
-                   gi_EvtRead++ ;
-                   gi_EvtTot++ ;    
- printf("complete event --------------------------------------------------\n");
-                }
              }// now we have stored a new board contents into Event structure
+             mBuffer[evID].board[ boardId ] = boardId ;
+             evtCtrl.evtStat[ iDx ]++ ;
+             evtCtrl.pcTime[ iDx ] = g_actTime ;
+
+             if (++mBuffer[evID].nBoard == g_actBoards ) {
+                snprintf(str,MXSTR,"%5d complete event %8d %8d %2d",mBuffer[evID].evNum,evtCtrl.evtBuf[iDx],iDx,evtCtrl.evtStat[ iDx ]);
+                factOut(kDebug,-1, str ) ;
+                //complete event read ---> flag for next processing
+                evtCtrl.evtStat[ iDx ] = 99;
+                gi_EvtRead++ ;
+                gi_EvtTot++ ;    
+             }
 
 EndBuf:
@@ -700,4 +638,5 @@
 
         } else {                        //we are reading event header
+           qread+=jrd ;
            rd[i].bufPos += jrd ;
            rd[i].bufLen -= jrd ;
@@ -708,6 +647,15 @@
                   && rd[i].rBuf->B[k+1] == start.B[0] ) break ;
               }
+
+
+              for (k=0; k<rd[i].bufPos -1 ; k++) {
+                 if (rd[i].rBuf->B[k  ] == start.B[1]
+                  && rd[i].rBuf->B[k+1] == start.B[0] ) break ;
+              }
+
               if (k >= rd[i].bufPos-1 ) {   //no start of header found
- printf("no start of header found !!!!\n");
+                 snprintf(str,MXSTR,"no start of header on port%d", i ) ;
+                 factOut(kWarn,666, str ) ;
+
                  rd[i].bufPos = 0 ;
                  rd[i].bufLen = head_len ;
@@ -719,10 +667,9 @@
               if ( rd[i].bufPos > MIN_LEN ) {
                  goodhed++;
-                 rd[i].fadLen = ntohs(rd[i].rBuf->S[1])*2 ; ///???
+                 rd[i].fadLen = ntohs(rd[i].rBuf->S[1])*2 ; 
                  rd[i].fadVers= ntohs(rd[i].rBuf->S[2]) ;
-                 rd[i].evtID  = ntohl(rd[i].rBuf->I[4]) ;
+                 rd[i].evtID  = ntohl(rd[i].rBuf->I[4]) ; //(FADevt)
                  rd[i].runID  = ntohl(rd[i].rBuf->I[11]) ;
- printf("received event %d %d\n",rd[i].evtID,i);
-                    if (rd[i].runID ==0 ) rd[i].runID = myRun ;
+if (rd[i].runID ==0 ) rd[i].runID = myRun ;
                  rd[i].bufTyp = 1 ;       //ready to read full record
                  rd[i].bufLen = rd[i].fadLen - rd[i].bufPos ;
@@ -734,25 +681,63 @@
     } //finished trying to read all sockets
 
-
+int qwait=0, qdel=0, qskip=0 ;
     g_actTime = time(NULL) ;
     if ( g_actTime > gi_SecTime ) {
+         gi_SecTime = g_actTime ;
 //       PrintRate() ;
 
+
        //loop over all active events and flag those older than read-timeout
-
-       int kd = evtCtrl.readPtr - evtCtrl.writePtr ;
+       //delete those that are written to disk ....
+
+       int kd = evtCtrl.lastPtr - evtCtrl.frstPtr ;
        if ( kd < 0 ) kd+= (MAX_EVT*MAX_RUN) ;
-       for ( k=evtCtrl.writePtr; k<(evtCtrl.writePtr+kd); k++ ) {
+
+       int k1=evtCtrl.frstPtr;
+       for ( k=k1; k<(k1+kd); k++ ) {
           int k0 = k % (MAX_EVT*MAX_RUN) ;
-
+//would be better to use bitmaps for evtStat (allow '&' instead of multi-if)
           if (evtCtrl.evtStat[k0] > 0
-           && evtCtrl.evtStat[k0] < 90
-           && evtCtrl.pcTime[k0] < g_actTime-10 ) {
-             evtCtrl.evtStat[k0] = 91 ;
+           && evtCtrl.evtStat[k0] < 90 ) {
+
+           qwait++; 
+
+           if( evtCtrl.pcTime[k0] < g_actTime-10 ) {
+             int id =evtCtrl.evtBuf[k0] ;
+             snprintf(str,MXSTR,"%5d skip short evt %8d %8d %2d",mBuffer[id].evNum,evtCtrl.evtBuf[k0],k0 ,evtCtrl.evtStat[k0]);
+             factOut(kWarn,601, str ) ;
+             evtCtrl.evtStat[k0] = 91 ;      //timeout for incomplete events
              gi_EvtBad++ ;
              gi_EvtTot++ ;    
+             qskip++; 
+           } 
+
+
+          } else if (evtCtrl.evtStat[k0] >= 900 ) {
+
+              int id =evtCtrl.evtBuf[k0] ;
+              snprintf(str,MXSTR,"%5d free event buffer (written) %3d", mBuffer[id].evNum, mBuffer[id].nBoard ) ;
+              factOut(kDebug,-1, str ) ;
+              mBufFree(id) ;               //event written--> free memory
+              evtCtrl.evtStat[k0] = -1; 
+              qdel++; 
+              qtot++;
+          }
+
+          if ( k0 == evtCtrl.frstPtr && evtCtrl.evtStat[k0] <0 ) {
+             evtCtrl.frstPtr = (evtCtrl.frstPtr+1) % (MAX_EVT*MAX_RUN) ;
           }
        }
+
+qconn=0 ;
+int ib ;
+for (ib=0; ib<NBOARDS; ib++) qconn+=gi_NumConnect[ib] ;
+
+snprintf(str,MXSTR,"bfr%5d skp%4d free%4d (tot%7d) mem%9lu rd%10d %3d",qwait,qskip,qdel,qtot,gi_usedMem,qread,qconn);
+factStat(kInfo,-1, str ) ;
+qread=0 ;
     }
+
+
 
 
@@ -765,16 +750,86 @@
           xwait.tv_sec = 0;
           xwait.tv_nsec= 2000000 ;  // sleep for ~2 msec
-//          xwait.tv_nsec= 10000000 ;  // sleep for ~10 msec
        }
-//       printf("sleeping ...\n");
        nanosleep( &xwait , NULL ) ;
     }
 
-
-
-
  } //and do next loop over all sockets ...
-  
-      return NULL;
+
+ //must quit eventbuilding
+ snprintf(str,MXSTR,"stop reading ...");
+ factOut(kInfo,-1, str ) ;
+
+ //flag all events as 'read finished'
+ int kd = evtCtrl.lastPtr - evtCtrl.frstPtr ;
+ if ( kd < 0 ) kd+= (MAX_EVT*MAX_RUN) ;
+
+ int k1=evtCtrl.frstPtr;
+
+ for ( k=k1; k<(k1+kd); k++ ) {
+    int k0 = k % (MAX_EVT*MAX_RUN) ;
+    if (evtCtrl.evtStat[k0] > 0 
+     && evtCtrl.evtStat[k0] < 90 ) {
+       evtCtrl.evtStat[k0] = 91 ;    
+       gi_EvtBad++ ;
+       gi_EvtTot++ ;    
+    }
+ }
+
+ //must close all open sockets ...
+ snprintf(str,MXSTR,"close all sockets ...");
+ factOut(kInfo,-1, str ) ;
+ for (i=0; i<MAX_SOCK; i++)    
+    if (rd[i].sockStat ==0 ) {  
+       j=close(rd[i].socket) ;
+       if (j>0) {
+          snprintf(str,MXSTR,"Error closing socket %d | %m",i);
+          factOut(kFatal,771, str ) ;
+       }
+       rd[i].sockStat = -1 ;        //flag (try to reopen next round)
+       gi_NumConnect[ rd[i].board ]-- ;
+    }
+
+ xwait.tv_sec = 0;
+ xwait.tv_nsec= 2000000 ;  // sleep for ~2 msec
+ nanosleep( &xwait , NULL ) ;
+ gi_runStat = -11 ;  //inform all that no update to happen any more
+
+
+ int minclear = 900 ; //usually wait until writing finished (stat 900)
+ if (g_runStat <-1 ) minclear = 0 ;  //in case of abort clear all
+
+
+ //and clear all buffers (might have to wait until all others are done)
+ snprintf(str,MXSTR,"clear all buffers ...");
+ factOut(kInfo,-1, str ) ;
+ int numclear=1 ;
+ while (numclear > 0 ) {
+    numclear = 0 ;
+    int kd = evtCtrl.lastPtr - evtCtrl.frstPtr ;
+    if ( kd < 0 ) kd+= (MAX_EVT*MAX_RUN) ;
+
+    int k1=evtCtrl.frstPtr;
+    for ( k=k1; k<(k1+kd); k++ ) {
+       int k0 = k % (MAX_EVT*MAX_RUN) ;
+       if (evtCtrl.evtStat[k0] > minclear ) {
+         int id =evtCtrl.evtBuf[k0] ;
+          mBufFree(id) ;               //event written--> free memory
+          evtCtrl.evtStat[k0] = -1; 
+       } else if (evtCtrl.evtStat[k0] > 0) numclear++ ;  //writing is still ongoing...
+
+       if ( k0 == evtCtrl.frstPtr && evtCtrl.evtStat[k0] <0 ) 
+          evtCtrl.frstPtr = (evtCtrl.frstPtr+1) % (MAX_EVT*MAX_RUN) ;
+    }
+
+    xwait.tv_sec = 0;
+    xwait.tv_nsec= 2000000 ;  // sleep for ~2 msec
+    nanosleep( &xwait , NULL ) ;
+ }
+
+ snprintf(str,MXSTR,"Exit read Process ...");
+ factOut(kInfo,-1, str ) ;
+ gi_runStat = -99 ;
+ return 0;
+
 } /*-----------------------------------------------------------------*/
 
@@ -782,158 +837,321 @@
 void *procEvt( void *ptr ) {
 /* *** main loop processing file, including SW-trigger */
-  int numProc ;
-  int k,k1,k2,kd ;
-
-  while (g_runStat > 0) {
-
-
-     kd = evtCtrl.readPtr - evtCtrl.writePtr ;
+  int numProc, numWait ;
+  int k ;
+  struct timespec xwait ;
+  char str[MXSTR] ;
+
+  cpu_set_t mask;
+  int cpu = 5 ;   //process thread  (will be several in final version)
+
+  snprintf(str,MXSTR,"Starting process-thread");
+  factOut(kInfo,-1, str ) ;
+
+/* CPU_ZERO initializes all the bits in the mask to zero. */
+   CPU_ZERO( &mask );
+/* CPU_SET sets only the bit corresponding to cpu. */
+   CPU_SET( cpu, &mask );
+/* sched_setaffinity returns 0 in success */
+   if ( sched_setaffinity( 0, sizeof(mask), &mask ) == -1 ) {
+      snprintf(str,MXSTR,"P ---> can not create affinity to %d",cpu);
+      factOut(kWarn,-1, str ) ;
+   }
+
+
+  while (g_runStat > -2) {   //in case of 'exit' we still must process pending events
+
+     numWait = numProc = 0 ;
+     int kd = evtCtrl.lastPtr - evtCtrl.frstPtr ;
      if ( kd < 0 ) kd+= (MAX_EVT*MAX_RUN) ;
-     k1=evtCtrl.writePtr;
-     k2=evtCtrl.writePtr+kd;
-
-     numProc = 0 ;
-     if (gp_EvtTot < gi_EvtTot) {
-        for ( k=k1; k<k2; k++ ) {
-           int k0 = k % (MAX_EVT*MAX_RUN) ;
-
-           if (evtCtrl.evtStat[k0] > 90 && evtCtrl.evtStat[k0] <500) {
-              //ready to be processed ...
-              int      id   = evtCtrl.evtBuf[k0] ;
-              uint32_t irun = mBuffer[id].runNum ;
-              int      ievt = mBuffer[id].evNum ;
-printf("processing %d %d %d %d\n",ievt,k,evtCtrl.evtStat[k0],evtCtrl.writePtr) ;
-              numProc++ ;
-              evtCtrl.evtStat[k0] = 501 ;
-              gp_EvtTot++ ;
+
+     int k1=evtCtrl.frstPtr;
+     for ( k=k1; k<(k1+kd); k++ ) {
+        int k0 = k % (MAX_EVT*MAX_RUN) ;
+//would be better to use bitmaps for evtStat (allow '&' instead of multi-if)
+        if (evtCtrl.evtStat[k0] > 90 && evtCtrl.evtStat[k0] <500) {
+           int      id   = evtCtrl.evtBuf[k0] ;
+           uint32_t irun = mBuffer[id].runNum ;
+           int      ievt = mBuffer[id].evNum ;
+           int      roi  = mBuffer[id].nRoi ;
+//snprintf(str,MXSTR,"P processing %d %d %d %d",ievt,k,id,evtCtrl.evtStat[k0]) ;
+//factOut(kDebug,-1, str ) ;
+
+//make sure unused pixels/tmarks are cleared to zero
+           int ip,it,dest,ib;
+           for (ip=0; ip<NPIX; ip++) {
+             if (mBuffer[id].fEvent->StartPix[ip] == -1 ) {
+                dest= ip*roi ;
+                bzero( &mBuffer[id].fEvent->Adc_Data[dest], roi*2) ;
+             }
            }
+           for (it=0; it<NTMARK; it++) {
+             if (mBuffer[id].fEvent->StartTM[it] == -1 ) {
+                dest= it*roi + NPIX*roi ;
+                bzero( &mBuffer[id].fEvent->Adc_Data[dest], roi*2) ;
+             }
+           }
+//and set correct event header ; also check for consistency in event
+          mBuffer[id].fEvent->Roi = roi ;
+          mBuffer[id].fEvent->EventNum = ievt ;
+          mBuffer[id].fEvent->TriggerType = 0 ; // TBD
+          mBuffer[id].fEvent->SoftTrig = 0 ;
+          for (ib=0; ib<NBOARDS; ib++) {
+             mBuffer[id].fEvent->BoardTime[ib] = 123 ;
+
+
+
+
+           }
+           numProc++ ;
+           evtCtrl.evtStat[k0] = 520 ;
+           gp_EvtTot++ ;
+        } else if ( evtCtrl.evtStat[k0] >=0 && evtCtrl.evtStat[k0] < 90 ) {
+           numWait++ ;
         }
      }
+
+     if ( gi_runStat < -10 && numWait == 0) {  //nothing left to do
+        snprintf(str,MXSTR,"Exit Processing Process ...");
+        factOut(kInfo,-1, str ) ;
+        gp_runStat = -22 ;                     //==> we should exit
+        return 0 ;
+     }
+
      if (numProc == 0) {
         //seems we have nothing to do, so sleep a little
         xwait.tv_sec = 0;
-        xwait.tv_nsec= 10000000 ;  // sleep for ~10 msec
+        xwait.tv_nsec= 2000000 ;  // sleep for ~2 msec
         nanosleep( &xwait , NULL ) ;
      }
+     gp_runStat = gi_runStat ;
 
   }
-  return NULL;
+
+  //we are asked to abort asap ==> must flag all remaining events 
+  //   when gi_runStat claims that all events are in the buffer...
+
+  snprintf(str,MXSTR,"Abort Processing Process ...");
+  factOut(kInfo,-1, str ) ;
+  int kd = evtCtrl.lastPtr - evtCtrl.frstPtr ;
+  if ( kd < 0 ) kd+= (MAX_EVT*MAX_RUN) ;
+
+  int k1=evtCtrl.frstPtr;
+  for ( k=k1; k<(k1+kd); k++ ) {
+     int k0 = k % (MAX_EVT*MAX_RUN) ;
+     if (evtCtrl.evtStat[k0] >=0 && evtCtrl.evtStat[k0] <500) {
+        evtCtrl.evtStat[k0] = 555 ; //flag event as 'processed'
+     }
+  }
+
+  gp_runStat = -99 ;
+
+  return 0;
   
 } /*-----------------------------------------------------------------*/
 
+int CloseRunFile(uint32_t runId, uint32_t closeTime) {
+/* close run runId (all all runs if runId=0) */
+/* return: 0=close scheduled / >0 already closed / <0 does not exist */
+  int j ;
+
+  if (runId == 0 ) {
+     for ( j=0; j<MAX_RUN; j++) {
+        if ( runCtrl[j].fileId == 0 ) {  //run is open
+           runCtrl[j].closeTime = closeTime ;
+        }
+     }
+     return 0 ;
+  }
+
+
+  for ( j=0; j<MAX_RUN; j++) {
+     if ( runCtrl[j].runId == runId ) {
+        if ( runCtrl[j].fileId == 0 ) {  //run is open
+           runCtrl[j].closeTime = closeTime ;
+           return 0;
+        } else if ( runCtrl[j].fileId <0 ) { //run not yet opened
+           runCtrl[j].closeTime = closeTime ;
+           return 0;
+        } else {     // run already closed
+           return +1;
+        }
+     }
+  }   //we only reach here if the run was never created
+  return -1;
+
+} /*-----------------------------------------------------------------*/
+
 
 void *writeEvt( void *ptr ) {
 /* *** main loop writing event (including opening and closing run-files */
 
-  int  numWrite = 0 ;
-  int j,id,irun,ievt ;
-
-  while (g_runStat > 0) {           //loop until global variable g_stop is set
-
-    //loop over buffered events and check if something to write ...
-
-    if ( gp_EvtTot == gw_EvtTot ) {
-       //there is for sure nothing to do --> sleep a little
-       xwait.tv_sec = 0;
-       xwait.tv_nsec= 10000000 ;  // sleep for ~10 msec
-       nanosleep( &xwait , NULL ) ;
-
-    } else {  //go through evtCtrl list to check if there might be something
-
-       //if run-file not yet opened==> open runfile (better to store headers in own structure ?)
-
-       //if eventid == next event for run ==> write it (or flag it)
-       //if eventid > next event exists, and nothing new for >time out ==> write it
-       //if nothing for this run for >timeout ==> close run
-
-       int kd = evtCtrl.readPtr - evtCtrl.writePtr ;
-       if ( kd < 0 ) kd+= (MAX_EVT*MAX_RUN) ;
-       int k,k1,k2 ;
-
-
-       k1=evtCtrl.writePtr;
-       k2=evtCtrl.writePtr+kd;
-
-       int evtTot=gw_EvtTot ;
-       for ( k=k1; k<k2; k++ ) {
-          int k0 = k % (MAX_EVT*MAX_RUN) ;
-
-          if (evtCtrl.evtStat[k0] > 500 ) { //ready to be written ...
-             id   = evtCtrl.evtBuf[k0] ;
-             irun = mBuffer[id].runNum ;
-             ievt = mBuffer[id].evNum ;
-
-             for ( j=0; j<MAX_RUN; j++) {
-                if ( runCtrl[j].runId == irun ) break ;
-             }
-             if ( j >= MAX_RUN ) {
- printf("error: can not find run %d\n", irun);
- exit(111);
-             }
-
-             if (runCtrl[j].fileId < 0 ) {
- printf("open new run_file %d\n",irun) ;
-                runCtrl[j].fileId = 999  ; // should be a function call
-                runCtrl[j].nextEvt= 0;
-                runCtrl[j].lastTime=g_actTime ;
-             }
-
-             if (runCtrl[j].nextEvt == ievt ) {  //write this event
- printf("write event %d (run %d %d)\n",ievt,irun,evtCtrl.evtStat[k0] ) ;
-                runCtrl[j].nextEvt= ievt+1;
-                runCtrl[j].lastTime=g_actTime ;
-                evtCtrl.evtStat[k0]= -1 ;
-                gw_EvtTot++ ;
-                numWrite++ ;
-//                evtCtrl.writePtr=k+1;
-             } else if ( ievt < runCtrl[j].nextEvt ) {
- printf("delayed event (run %d %d %d) skipped\n",ievt,irun,evtCtrl.evtStat[k0] ) ;
-                evtCtrl.evtStat[k0]= -1 ;
-//                evtCtrl.writePtr=k+1;
-                gw_EvtTot++ ;
-                numWrite++ ;
-             } 
-          }
-
-
-
-          if ( runCtrl[j].lastTime < g_actTime-15) {
- printf("non existing event skip %d (run %d -> %d)\n",runCtrl[j].nextEvt,irun,ievt) ;
-             runCtrl[j].nextEvt++;
-             numWrite++;
-          } 
-
-          for ( j=0; j<MAX_RUN; j++) {
-             if ( runCtrl[j].runId >0 && runCtrl[j].lastTime < g_actTime-120) {
- printf("close run %d (timeout)\n",irun) ;
-                runCtrl[j].fileId = -2 ;
-                runCtrl[j].runId  =  0 ;
-             }
-          }
-          if (numWrite == 0 ) {
-             //nothing to do at the moment ==> sleep a little
-             xwait.tv_sec = 0;
-             xwait.tv_nsec= 10000000 ;  // sleep for ~10 msec
-             nanosleep( &xwait , NULL ) ;
-          }
-
-       }
-     }
-
-
-
-
-
-
-
-
-
-
-
-
-  return NULL;
+  int  numWrite, numWait ;
+  int k,j ;
+  struct timespec xwait ;
+  char str[MXSTR] ;
+
+  cpu_set_t mask;
+  int cpu = 3 ;   //write thread
+
+  snprintf(str,MXSTR,"Starting write-thread");
+  factOut(kInfo,-1, str ) ;
+
+/* CPU_ZERO initializes all the bits in the mask to zero. */
+   CPU_ZERO( &mask );
+/* CPU_SET sets only the bit corresponding to cpu. */
+   CPU_SET( cpu, &mask );
+/* sched_setaffinity returns 0 in success */
+   if ( sched_setaffinity( 0, sizeof(mask), &mask ) == -1 ) {
+      snprintf(str,MXSTR,"W ---> can not create affinity to %d",cpu);
+   }
+
+  int lastRun = 0 ; //usually run from last event still valid
+
+  while (g_runStat >-2) {
+
+     numWait = numWrite = 0 ;
+     int kd = evtCtrl.lastPtr - evtCtrl.frstPtr ;
+     if ( kd < 0 ) kd+= (MAX_EVT*MAX_RUN) ;
+
+     int k1=evtCtrl.frstPtr;
+     for ( k=k1; k<(k1+kd); k++ ) {
+        int k0 = k % (MAX_EVT*MAX_RUN) ;
+//would be better to use bitmaps for evtStat (allow '&' instead of multi-if)
+        if (evtCtrl.evtStat[k0] > 500 && evtCtrl.evtStat[k0] < 900) {
+           int      id   = evtCtrl.evtBuf[k0] ;
+           uint32_t irun = mBuffer[id].runNum ;
+           int      ievt = mBuffer[id].evNum ;
+
+           if (runCtrl[lastRun].runId == irun ) {
+              j = lastRun ;
+           } else {
+              //check which fileID to use (or open if needed)
+              for ( j=0; j<MAX_RUN; j++) {
+                 if ( runCtrl[j].runId == irun ) break ;
+              }
+              if ( j >= MAX_RUN ) {
+                 snprintf(str,MXSTR,"W error: can not find run %d for event %d in %d", irun,ievt,id);
+                 factOut(kFatal,901, str ) ;
+for ( j=0; j<MAX_RUN; j++) printf("j %d   run.j %d   run %d\n",j,runCtrl[j].runId,irun );
+exit(111);
+              }
+              lastRun = j ;
+           }
+
+           if (runCtrl[j].fileId < 0 ) {
+              actRun.Version =  1 ;
+              actRun.RunType = -1 ;
+              actRun.NBoard  = NBOARDS ;
+              actRun.NPix    = NPIX ;
+              actRun.NTm     = NTMARK ;
+              actRun.Nroi    = mBuffer[id].nRoi ;
+//            actRun.FADhead = mBuffer[id].FADhead ;  //to be corrected
+              runCtrl[j].nextEvt= 0;
+              runCtrl[j].lastTime=g_actTime ;
+              runCtrl[j].fileHd = runOpen(irun,  &actRun, sizeof(actRun) ) ;
+              if (runCtrl[j].fileHd == NULL ) {
+                 snprintf(str,MXSTR,"W could not open a file for run %d",irun);
+                 factOut(kError,502, str ) ;
+                 runCtrl[j].fileId = 99 ;
+              } else {
+                 snprintf(str,MXSTR,"W opened new run_file %d",irun) ;
+                 factOut(kInfo,-1, str ) ;
+                 runCtrl[j].fileId = 0 ;
+              }
+
+           }
+
+           if (runCtrl[j].fileId > 0 ) {
+              snprintf(str,MXSTR,"W no open file for this run %d",irun) ;
+              factOut(kDebug,123,str) ;
+              evtCtrl.evtStat[k0] = 902 ;
+           } else {
+              int i=runWrite(runCtrl[j].fileHd, mBuffer[id].fEvent, sizeof(mBuffer[id]) );
+              if (i<0) {
+                 snprintf(str,MXSTR,"W error writing event for run %d",irun) ;
+                 factOut(kError,503, str ) ;
+                 evtCtrl.evtStat[k0] = 901 ;
+                 //close run
+                 i=runClose(runCtrl[j].fileHd, &runTail[j], sizeof(runTail[j]) );
+                 if (i<0) {
+                    snprintf(str,MXSTR,"W error closing run %d",irun) ;
+                    factOut(kError,503, str ) ;
+                 } else {
+                    snprintf(str,MXSTR,"W closed run %d because of write error",irun) ;
+                    factOut(kInfo,503, str ) ;
+                 }
+                 runCtrl[j].fileId = 9999 ;
+              } else {
+                 runCtrl[j].lastTime = g_actTime; 
+                 evtCtrl.evtStat[k0] = 901 ;
+                 snprintf(str,MXSTR,"%5d successfully wrote for run %d id %5d",ievt,irun,k0);
+                 factOut(kDebug,504, str ) ;
+              }
+           }
+        } else if (evtCtrl.evtStat[k0] > 0 ) numWait++ ;
+     }
+
+     //check if we should close a run ...
+     for ( j=0; j<MAX_RUN; j++) {
+        if ( runCtrl[j].fileId==0    
+          && (  runCtrl[j].closeTime < g_actTime  
+              ||runCtrl[j].lastTime  < g_actTime-120) ) {
+           int i=runClose(runCtrl[j].fileHd, &runTail[j], sizeof(runTail[j]) );
+           if (i<0) {
+              snprintf(str,MXSTR,"error closing run %d %d",runCtrl[j].runId,i) ;
+              factOut(kError,506, str ) ;
+              runCtrl[j].fileId = 888 ;
+           } else {
+              snprintf(str,MXSTR,"closing run %d ok  BBB",runCtrl[j].runId);
+              factOut(kInfo,507, str ) ;
+              runCtrl[j].fileId = 7777 ;
+           }
+        }
+     }
+
+     if (numWrite == 0) {
+        //seems we have nothing to do, so sleep a little
+        xwait.tv_sec = 0;
+        xwait.tv_nsec= 2000000 ;  // sleep for ~2 msec
+        nanosleep( &xwait , NULL ) ;
+     }
+
+     if ( gi_runStat < -10 && numWait == 0) {  //nothing left to do
+        snprintf(str,MXSTR,"Finish Write Process ...");
+        factOut(kInfo,-1, str ) ;
+        gw_runStat = -22 ;                     //==> we should exit
+        goto closerun ;
+     }
+     gw_runStat = gi_runStat ;
+
   }
 
-  return NULL;
+  //must close all open files ....
+  snprintf(str,MXSTR,"Abort Writing Process ...");
+  factOut(kInfo,-1, str ) ;
+closerun:
+  snprintf(str,MXSTR,"Close all open files ...");
+  factOut(kInfo,-1, str ) ;
+  for ( j=0; j<MAX_RUN; j++) 
+     if ( runCtrl[j].runId >0 ) {
+        int i=runClose(runCtrl[j].fileHd, &runTail[j], sizeof(runTail[j]) );
+        if (i<0) {
+           snprintf(str,MXSTR,"error closing run %d %d",runCtrl[j].runId,i) ;
+           factOut(kError,506, str ) ;
+           runCtrl[j].fileId = 888 ;
+        } else {
+           snprintf(str,MXSTR,"closing run %d ok  AAA",runCtrl[j].runId);
+           factOut(kInfo,507, str ) ;
+           runCtrl[j].fileId = 7777 ;
+        }
+     }
+
+  gw_runStat = -99; 
+  snprintf(str,MXSTR,"Exit Writing Process ...");
+  factOut(kInfo,-1, str ) ;
+  return 0;
+
+
+  
 
 } /*-----------------------------------------------------------------*/
@@ -941,18 +1159,93 @@
 
 
+
+void StartEvtBuild() {
+
+  int i,j,imax,status,th_ret[50] ;
+  pthread_t thread[50] ;
+  struct timespec xwait ;
+  uint32_t actime ;
+
+  gi_runStat = gp_runStat = gw_runStat = 0 ;
+
+  snprintf(str,MXSTR,"Starting EventBuilder");
+  factOut(kInfo,-1, str ) ;
+
+
+   evtCtrl.frstPtr = 0 ;
+   evtCtrl.lastPtr = 0 ;
+
+   actime = g_actTime + 50000000 ;
+/* initialize run control logics */
+   for (i=0; i<MAX_RUN; i++) {
+      runCtrl[i].runId = 0 ;
+      runCtrl[i].lastTime = 0 ;
+      runCtrl[i].closeTime = time(NULL) + 3600*24*7; 
+
+      runCtrl[i].nextEvt = 0 ;
+      runCtrl[i].fileId = -2 ;
+
+      runTail[i].nEventsOk =
+      runTail[i].nEventsRej =
+      runTail[i].nEventsBad =
+      runTail[i].PCtime0 =
+      runTail[i].PCtimeX = 0 ;
+   }
+
+//start all threads (more to come) when we are allowed to ....
+  while (g_runStat == 0 ) {
+     xwait.tv_sec = 0;
+     xwait.tv_nsec= 2000000 ;  // sleep for ~2 msec
+     nanosleep( &xwait , NULL ) ;
+  }
+
+  i=0 ;
+  th_ret[i] = pthread_create( &thread[i], NULL, readFAD,  NULL );
+  i++;
+  th_ret[i] = pthread_create( &thread[i], NULL, procEvt,  NULL );
+  i++;
+  th_ret[i] = pthread_create( &thread[i], NULL, writeEvt, NULL );
+  i++;
+  imax=i ;
+
+
+
+
 /*
-int main() {
-  int i,th_ret[50] ;
-  pthread_t thread[50] ;
-
-  initReadFAD() ;
-  i=0 ;
-  th_ret[i] = pthread_create( &thread[i], NULL, readFAD,  (void*) i++ );
-  th_ret[i] = pthread_create( &thread[i], NULL, procEvt,  (void*) i++ );
-  th_ret[i] = pthread_create( &thread[i], NULL, writeEvt, (void*) i++ );
-
-  for(;;) { sleep(1); }
-
-
-}
-*/
+
+     xwait.tv_sec = 20;;
+     xwait.tv_nsec= 0 ;  // sleep for ~20sec
+     nanosleep( &xwait , NULL ) ;
+
+
+     printf("close all runs in 2 seconds\n");
+
+
+     CloseRunFile( 0, time(NULL)+2) ;
+
+     xwait.tv_sec = 5;;
+     xwait.tv_nsec= 0 ;  // sleep for ~20sec
+     nanosleep( &xwait , NULL ) ;
+
+     printf("setting g_runstat to -1\n");
+
+     g_runStat = -1 ;
+
+
+ */
+
+
+
+
+
+
+
+
+
+//wait for all threads to finish
+  for (i=0; i<imax; i++) {
+     j = pthread_join ( thread[i], (void **)&status) ;
+  }
+
+} /*-----------------------------------------------------------------*/
+
Index: /trunk/FACT++/src/EventBuilder.h
===================================================================
--- /trunk/FACT++/src/EventBuilder.h	(revision 10962)
+++ /trunk/FACT++/src/EventBuilder.h	(revision 10963)
@@ -20,5 +20,11 @@
 extern int  g_actTime   ;  //actual time, to be updated regularily
 extern int  g_runStat   ;  //main steering variable
-extern int  g_actBoards ;  //number of boards that should exist
+extern int  g_actBoards ;  //number of boards that should exist at the moment
+extern size_t g_maxMem  ;  //maximum memory allowed for buffer
+
+extern PIX_MAP g_pixMap[NPIX] ;
+
+extern int  g_maxBoards ;  //maximum number of boards to be initialized
+extern FACT_SOCK g_port[NBOARDS] ;  // .port = baseport, .addr=string of IP-addr in dotted-decimal "ddd.ddd.ddd.ddd"
 
 extern uint gi_SecRate[MAX_SOCK] ;    //MAX_SOCK defined in FACTEvent.h
@@ -32,9 +38,15 @@
 extern uint gi_EvtBad   ;
 extern uint gi_EvtTot   ;
+extern int  gi_maxSocks ;    //maximum sockets that will be tried
+extern size_t gi_usedMem ;
+extern int  gi_runStat ;
+
+extern uint gp_EvtTot   ;
+extern int  gp_runStat ;
 extern uint gw_EvtTot   ;
-extern uint gp_EvtTot   ;
+extern int  gw_runStat ;
 
-//#define error Error
-//extern void Error(int severity, int errnum, const char *fmt, ...);
+
+
 
 #ifdef __cplusplus
Index: /trunk/FACT++/src/FAD.h
===================================================================
--- /trunk/FACT++/src/FAD.h	(revision 10962)
+++ /trunk/FACT++/src/FAD.h	(revision 10963)
@@ -29,4 +29,18 @@
 // Data structures
 //
+
+typedef struct{
+  int hardID ;       //hardware ID
+  int pos_i ;        //geometrical positon row 
+  int pos_j ;        //                    column
+  int G_APD ;        //G-APD identifier
+  double V_op ;      //operation voltage
+  int HV_B ;         //HV Board
+  int HV_C ;         //HV Channel
+  double pos_X ;     //geometrical position in pixel units
+  double pos_Y ;     //
+} PIX_MAP ;
+
+
 typedef struct {
 
@@ -76,5 +90,5 @@
 #define NBOARDS      40      // max. number of boards
 #define NPIX       1440      // max. number of pixels
-#define NTMARK      180      // max. number of timeMarker signals
+#define NTMARK      160      // max. number of timeMarker signals
 #define MAX_SOCK    280      // NBOARDS * 7
 
@@ -101,21 +115,18 @@
 
 typedef struct {
+  uint16_t Roi ;            // #slices per pixel (same for all pixels and tmarks)
   uint32_t EventNum ;       // EventNumber as from FTM
   uint16_t TriggerType ;    // Trigger Type from FTM
-  uint16_t Roi ;            // #slices per pixel (same for all pixels and tmarks)
 
   uint32_t SoftTrig ;       // SoftTrigger Info (TBD)
   uint32_t PCTime ;         // when did event start to arrive at PC
 
-   int16_t *StartPix ;      //First Channel per Pixel (Pixels sorted according Software ID)  ; -1 if not filled
-
-   int16_t *StartTM  ;      //First Channel for TimeMark (sorted Hardware ID) ; -1 if not filled
-
-  uint16_t *Adc_Data ;      // [ NPixels ] [ ROI ]  sorted softID
-
-  uint16_t *Adc_Tmark ;     // [ NTmark ] [ ROI ]   sorted hardID
-
-//this is highly redundant and should be reduced to usefull info [if any]
-  PEVNT_HEADER *FADhead;    // [ NBoards ] sorted Board Headers (according Hardware ID)
+  uint32_t BoardTime[NBOARDS];//
+
+   int16_t StartPix[NPIX];  // First Channel per Pixel (Pixels sorted according Software ID)  ; -1 if not filled
+
+   int16_t StartTM[NTMARK]; // First Channel for TimeMark (sorted Hardware ID) ; -1 if not filled
+
+  uint16_t Adc_Data[1];     // final length defined by malloc ....
 
 } EVENT ;
@@ -162,13 +173,17 @@
 //---------------------------------------------------------------
 
-#define MAX_RUN   64
-#define MAX_EVT   131072
+#define MAX_RUN   256
+#define MAX_EVT   32768  //don't worry, for events is MAX_RUN*MAX_EVT
+
+typedef void* FileHandle_t ;
 
 typedef struct {
   uint32_t runId ;       //run number
   uint32_t lastTime ;    //time when last event written so far
+  uint32_t closeTime ;   //time when run should be closed
   uint32_t nextEvt ;     //next event number to be written
   uint32_t waitEvt ;     //event that would be ready to be written
-   int32_t fileId ;      //id of open file
+   int32_t fileId  ;     //<0 never opened, 0=open, >0 closed
+  FileHandle_t fileHd ;   //fileHandle (NULL if not open)
    int16_t ctrlId[MAX_EVT] ; //index to buffId (sorted list; -1 =end)
   uint16_t buffId[MAX_EVT] ; //index to mBuffer(buffered raw data)
@@ -188,5 +203,7 @@
   int32_t nRoi   ;
   int32_t pcTime ;
+  int32_t evtLen ;
   EVENT   *fEvent  ;
+  PEVNT_HEADER *FADhead; //
 
 } WRK_DATA ;             //internal to eventbuilder
@@ -197,6 +214,6 @@
 
 typedef struct {
-  int readPtr ;             //index of reading
-  int writePtr ;            //index of writing
+  int frstPtr ;             //first used index
+  int lastPtr ;             //last  used index 
   int evtBuf[MAX_EVT*MAX_RUN] ;     //index of event in mBuffer
   int evtStat[MAX_EVT*MAX_RUN] ;    //status of event:
@@ -215,4 +232,11 @@
 } EVT_CTRL ;
 
+//---------------------------------------------------------------
+
+
+typedef struct {
+   struct sockaddr_in sockAddr ;
+   int    sockDef ; //<0 not defined/ ==0 not to be used/ >0 used
+} FACT_SOCK ; 
 
 
