Index: trunk/FACT++/src/EventBuilderWrapper.h
===================================================================
--- trunk/FACT++/src/EventBuilderWrapper.h	(revision 16106)
+++ trunk/FACT++/src/EventBuilderWrapper.h	(revision 16107)
@@ -12,5 +12,4 @@
 #include <boost/filesystem.hpp>
 #include <boost/date_time/posix_time/posix_time_types.hpp>
-#include <condition_variable>
 
 #include "DimWriteStatistics.h"
@@ -41,8 +40,6 @@
 #include "EventBuilder.h"
 
-extern "C" {
-    extern void StartEvtBuild();
-    extern int CloseRunFile(uint32_t runId, uint32_t closeTime, uint32_t maxEvt);
-}
+void StartEvtBuild();
+void CloseRunFile();
 
 // ========================================================================
@@ -59,17 +56,4 @@
     boost::thread fThreadMain;
 
-    enum CommandStates_t // g_runStat
-    {
-        kAbort      = -2,   // quit as soon as possible ('abort')
-        kExit       = -1,   // stop reading, quit when buffered events done ('exit')
-        kInitialize =  0,   // 'initialize' (e.g. dim not yet started)
-        kHybernate  =  1,   // do nothing for long time ('hybernate') [wakeup within ~1sec]
-        kSleep      =  2,   // do nothing ('sleep')                   [wakeup within ~10msec]
-        kModeFlush  = 10,   // read data from camera, but skip them ('flush')
-        kModeTest   = 20,   // read data and process them, but do not write to disk ('test')
-        kModeFlag   = 30,   // read data, process and write all to disk ('flag')
-        kModeRun    = 40,   // read data, process and write selected to disk ('run')
-    };
-
     enum
     {
@@ -82,5 +66,5 @@
     FAD::FileFormat_t fFileFormat;
 
-    uint32_t fMaxRun;
+    //uint32_t fMaxRun;
     uint32_t fLastOpened;
     uint32_t fLastClosed;
@@ -113,12 +97,11 @@
     Queue<pair<Time,array<uint32_t,4>>> fDimQueue3;
     Queue<pair<Time,array<uint16_t,2>>> fDimQueue4;
-    
-    bool fDebugStream;
-    bool fDebugRead;
-    bool fDebugLog;
 
     string   fPath;
-    uint64_t fNightAsInt;
+    uint32_t fNightAsInt;
     uint32_t fRunNumber;
+    int64_t  fRunInProgress;
+
+    array<uint16_t,2> fVecRoi;
 
 protected:
@@ -140,5 +123,5 @@
 
         // Get current night
-        const uint64_t night = Time().NightAsInt();
+        const uint32_t night = Time().NightAsInt();
         if (night==fNightAsInt)
             return true;
@@ -185,5 +168,5 @@
 public:
     EventBuilderWrapper(MessageImp &imp) : fMsg(imp),
-        fFileFormat(FAD::kNone), fMaxRun(0), fLastOpened(0), fLastClosed(0),
+        fFileFormat(FAD::kNone), /*fMaxRun(0),*/ fLastOpened(0), fLastClosed(0),
         fDimWriteStats  ("FAD_CONTROL", imp),
         fDimRuns        ("FAD_CONTROL/RUNS",               "I:5;C",
@@ -254,16 +237,4 @@
                                                            "|rateBytes[int]:Bytes read this cycle"
                                                            "|totBytes[int]:Bytes read (counter)"),
-        /*fDimStatistics2 ("FAD_CONTROL/STATISTICS2",        "I:1;I:280;X:40;I:40;I:4;I:4;I:2;I:2;I:3;C:40",
-                                                           "Event Builder status, events oriented"
-                                                           "|reset[int]:If increased, reset all counters"
-                                                           "|numRead[int]:How often sucessful read from N sockets per loop"
-                                                           "|gotByte[int]:number of bytes read per board"
-                                                           "|gotErr[int]:number of com. errors per board"
-                                                           "|evtStat[int]:number of evts read, completed, with errors, incomplete"
-                                                           "|procStat[int]:num. of evts proc., w probs, acc. or rej. by SW trigger"
-                                                           "|feedStat[int]:number of evts used or rejected by feedback system"
-                                                           "|wrtStat[int]:number of evts written to disk, with errors"
-                                                           "|runStat[int]:number of run opened, closed, with open or close errors"
-                                                           "|numConn[int]:number of sockets successfully opened per board"),*/
         fDimFileFormat("FAD_CONTROL/FILE_FORMAT",          "S:1", "|format[int]:Current file format"),
         fDimIncomplete("FAD_CONTROL/INCOMPLETE",           "X:1", "|incomplete[bits]:One bit per board"),
@@ -273,5 +244,5 @@
         fDimQueue3(std::bind(&EventBuilderWrapper::updateEvents, this, placeholders::_1)),
         fDimQueue4(std::bind(&EventBuilderWrapper::updateRoi, this, placeholders::_1)),
-        fDebugStream(false), fDebugRead(false), fDebugLog(false), fNightAsInt(0)
+        fNightAsInt(0), fRunInProgress(-1)
     {
         if (This)
@@ -279,4 +250,6 @@
 
         This = this;
+
+        fVecRoi.fill(0);
 
         memset(fNumEvts.data(), 0, sizeof(fNumEvts));
@@ -294,13 +267,9 @@
         //        What's the maximum time the eb need to abort?
         fThreadMain.join();
-
-        //ffMsg.Info("EventBuilder stopped.");
-
-        for (vector<DataProcessorImp*>::iterator it=fFiles.begin(); it!=fFiles.end(); it++)
-            delete *it;
-    }
-
-    set<uint32_t> fIsRunStarted;
+    }
+
     map<uint32_t, FAD::RunDescription> fExpectedRuns;
+
+    mutex mtx_newrun;
 
     uint32_t StartNewRun(int64_t maxtime, int64_t maxevt, const pair<string, FAD::Configuration> &ref)
@@ -311,21 +280,18 @@
             maxevt  = INT32_MAX;
 
+        if (!InitRunNumber())
+            return 0;
+
         const FAD::RunDescription descr =
         {
             uint32_t(maxtime),
             uint32_t(maxevt),
+            fNightAsInt,
             ref.first,
             ref.second,
         };
 
-        if (!InitRunNumber())
-            return 0;
-
-        // FIMXE: Maybe reset an event counter so that the mcp can count events?
-
-        //fMsg.Info(" ==> TODO: Set a limit on the size of fExpectedRuns!");
-
+        const lock_guard<mutex> lock(mtx_newrun);
         fExpectedRuns[fRunNumber] = descr;
-        fIsRunStarted.insert(fRunNumber);
         return fRunNumber++;
     }
@@ -333,4 +299,6 @@
     bool IsThreadRunning()
     {
+        if (fThreadMain.get_id()==boost::this_thread::get_id())
+            return true;
         return !fThreadMain.timed_join(boost::posix_time::microseconds(0));
     }
@@ -338,11 +306,4 @@
     void SetMaxMemory(unsigned int mb) const
     {
-        /*
-        if (mb*1000000<GetUsedMemory())
-        {
-            // ffMsg.Warn("...");
-            return;
-        }*/
-
         g_maxMem = size_t(mb)*1000000;
     }
@@ -356,16 +317,14 @@
         }
 
-        fLastMessage.clear();
+        //fLastMessage.clear();
 
         for (size_t i=0; i<40; i++)
             ConnectSlot(i, addr[i]);
 
-        g_runStat = kModeRun;
-        g_maxProc = 1;
-
         fMsg.Message("Starting EventBuilder thread");
 
         fThreadMain = boost::thread(StartEvtBuild);
     }
+
     void ConnectSlot(unsigned int i, const tcp::endpoint &addr)
     {
@@ -400,10 +359,4 @@
         // In this order
 
-        struct sockaddr_in addr; //IP for each socket
-        addr.sin_family      = AF_INET;
-        addr.sin_addr.s_addr = 0;
-        addr.sin_port        = 0;
-        memcpy(&g_port[i].sockAddr, &addr, sizeof(struct sockaddr_in));
-
         fDimIncomplete.setQuality(0);
         fDimIncomplete.Update(uint64_t(0));
@@ -413,4 +366,5 @@
         if (i>39)
             return;
+
         if (g_port[i].sockAddr.sin_port==0)
             return;
@@ -423,39 +377,9 @@
     {
         fMsg.Message("Signal abort to EventBuilder thread...");
-        g_reset = 1;
+        g_reset = 2;
     }
 
     void ResetThread(bool soft)
     {
-        /*
-         if (g_reset > 0)
-
-            * suspend reading
-            * reset = g_reset;
-            * g_reset=0
-
-            * reset% 10
-                == 0  leave event Buffers as they are
-                == 1  let all buffers drain (write (incomplete) events)
-                >  1  flush all buffers (do not write buffered events)
-
-            * (reset/10)%10
-                > 0   close all sockets and destroy them (also free the
-                      allocated read-buffers)
-                      recreate before resuming operation
-                      [ this is more than just close/open that can be
-                        triggered by e.g. close/open the base-socket ]
-
-            * (reset/100)%10
-                > 0   close all open run-files
-
-            * (reset/1000)
-                      sleep so many seconds before resuming operation
-                      (does not (yet) take into account time left when waiting
-                      for buffers getting empty ...)
-
-            * resume_reading
-
-         */
         fMsg.Message("Signal reset to EventBuilder thread...");
         g_reset = soft ? 101 : 102;
@@ -465,36 +389,11 @@
     {
         fMsg.Message("Signal exit to EventBuilder thread...");
-        g_runStat = kExit;
-    }
-
-    /*
-    void Wait()
-    {
-        fThread.join();
-        ffMsg.Message("EventBuilder stopped.");
-    }*/
-
-    void Hybernate() const { g_runStat = kHybernate; }
-    void Sleep()     const { g_runStat = kSleep;     }
-    void FlushMode() const { g_runStat = kModeFlush; }
-    void TestMode()  const { g_runStat = kModeTest;  }
-    void FlagMode()  const { g_runStat = kModeFlag;  }
-    void RunMode()   const { g_runStat = kModeRun;   }
-
-    // FIXME: To be removed
-    //void SetMode(int mode) const { g_runStat = mode; }
-
-    bool IsConnected(int i) const     { return gi_NumConnect[i]==7; }
-    bool IsConnecting(int i) const    { return !IsConnected(i) && !IsDisconnected(i); }
-    bool IsDisconnected(int i) const  { return gi_NumConnect[i]<=0 && g_port[i].sockDef==0; }
-    int  GetNumConnected(int i) const { return gi_NumConnect[i]; }
-    int GetNumFilesOpen() const       { return fFiles.size(); }
-
-    /*
-    bool IsConnected(int i) const     { return gi_NumConnect[i]>0; }
-    bool IsConnecting(int i) const    { return !IsConnected(i) && !IsDisconnected(i); }
-    bool IsDisconnected(int i) const  { return gi_NumConnect[i]<=0 && g_port[i].sockDef==0; }
-    int  GetNumConnected(int i) const { return gi_NumConnect[i]; }
-    */
+        g_reset = 1;
+    }
+
+    bool IsConnected(int i) const     { return gi_NumConnect[i]==1; }
+    bool IsConnecting(int i) const    { return gi_NumConnect[i]==0 && g_port[i].sockDef!=0; }
+    bool IsDisconnected(int i) const  { return gi_NumConnect[i]==0 && g_port[i].sockDef==0; }
+    bool IsRunInProgress() const { return fRunInProgress>=0; }
 
     void SetIgnore(int i, bool b) const { if (g_port[i].sockDef!=0) g_port[i].sockDef=b?-1:1; }
@@ -541,37 +440,4 @@
     }
 
-    void SetDebugLog(bool b) { fDebugLog = b; }
-
-    void SetDebugStream(bool b)
-    {
-        fDebugStream = b;
-        if (b)
-            return;
-
-        for (int i=0; i<40; i++)
-        {
-            if (!fDumpStream[i].is_open())
-                continue;
-
-            fDumpStream[i].close();
-
-            ostringstream name;
-            name << "socket_dump-" << setfill('0') << setw(2) << i << ".bin";
-            fMsg.Message("Closed file '"+name.str()+"'");
-        }
-    }
-
-    void SetDebugRead(bool b)
-    {
-        fDebugRead = b;
-        if (b || !fDumpRead.is_open())
-            return;
-
-        fDumpRead.close();
-        fMsg.Message("Closed file 'socket_events.txt'");
-    }
-
-//    size_t GetUsedMemory() const { return gi_usedMem; }
-
     void LoadDrsCalibration(const char *fname)
     {
@@ -582,26 +448,6 @@
     }
 
-    virtual int CloseOpenFiles() { CloseRunFile(0, 0, 0); return 0; }
-
-
-    /*
-     struct OpenFileToDim
-     {
-        int code;
-        char fileName[FILENAME_MAX];
-     };
-
-     SignalRunOpened(runid, filename);
-     // Send num open files
-     // Send runid, (more info about the run?), filename via dim
-
-     SignalEvtWritten(runid);
-     // Send num events written of newest file
-
-     SignalRunClose(runid);
-     // Send new num open files
-     // Send empty file-name if no file is open
-
-     */
+    virtual int CloseOpenFiles() { CloseRunFile(); return 0; }
+
 
     // -------------- Mapped event builder callbacks ------------------
@@ -611,33 +457,18 @@
         uint32_t values[5] =
         {
-            static_cast<uint32_t>(fFiles.size()),
-            0xffffffff,
-            0,
+            !fFile ? 0 : 1,
+            fFile ? fFile->GetRunId() : 0,
+            fFile ? fFile->GetRunId() : 0,
             fLastOpened,
             fLastClosed
         };
 
-        for (vector<DataProcessorImp*>::const_iterator it=fFiles.begin();
-             it!=fFiles.end(); it++)
-        {
-            const DataProcessorImp *file = *it;
-
-            if (file->GetRunId()<values[1])
-                values[1] = file->GetRunId();
-
-            if (file->GetRunId()>values[2])
-                values[2] = file->GetRunId();
-        }
-
-        fMaxRun = values[2];
-
         vector<char> data(sizeof(values)+fname.size()+1);
         memcpy(data.data(), values, sizeof(values));
         strcpy(data.data()+sizeof(values), fname.c_str());
-
         fDimRuns.Update(data);
     }
 
-    vector<DataProcessorImp*> fFiles;
+    shared_ptr<DataProcessorImp> fFile;
 
     void updateEvents(const pair<Time,array<uint32_t,4>> &stat)
@@ -647,63 +478,61 @@
     }
 
-    FileHandle_t runOpen(uint32_t runid, RUN_HEAD *h, size_t)
-    {
-        //fMsg.Info(" ==> TODO: Update run configuration in database!");
-
-        map<uint32_t,FAD::RunDescription>::iterator it = fExpectedRuns.begin();
-        while (it!=fExpectedRuns.end())
-        {
-            if (it->first<runid)
-            {
-                ostringstream str;
-                str << "runOpen - Missed run " << it->first << ".";
-                fMsg.Info(str);
-
-                fExpectedRuns.erase(it++);
-                continue;
-            }
-            if (it->first==runid)
-                break;
-            it++;
-        }
-
-        FAD::RunDescription desc;
-
-        if (it==fExpectedRuns.end())
-        {
-            ostringstream str;
-            str << "runOpen - Run " << runid << " wasn't expected (maybe manual triggers)";
-            fMsg.Warn(str);
-        }
-        else
-        {
-            desc = it->second;
-            fExpectedRuns.erase(it);
-        }
-
-        // Check if file already exists...
+    bool runOpen(const shared_ptr<EVT_CTRL2> &evt)
+    {
+        const uint32_t night = evt->runCtrl->night;
+        const uint32_t runid = evt->runNum>0 ? evt->runNum : time(NULL);
+
+        // If there is still an open file: close it
+        if (fFile)
+            runClose();
+
+        // Keep a copy of the currently valid drs calibration
+        // and associate it to the run control structure
+        evt->runCtrl->calib = shared_ptr<DrsCalibration>(new DrsCalibration(DataCalib::GetCalibration()));
+
+        // FIMXE: Check if file already exists...
+
+        // Crate the file
         DataProcessorImp *file = 0;
         switch (fFileFormat)
         {
-        case FAD::kNone:    file = new DataDump(fPath, fNightAsInt, runid,  fMsg); break;
-        case FAD::kDebug:   file = new DataDebug(fPath, fNightAsInt, runid, fMsg); break;
-        case FAD::kCfitsio: file = new DataWriteFits(fPath, fNightAsInt, runid,  fMsg); break;
-        case FAD::kFits:    file = new DataWriteFits2(fPath, fNightAsInt, runid,  fMsg); break;
-	case FAD::kRaw:     file = new DataWriteRaw(fPath, fNightAsInt, runid,   fMsg); break;
-	case FAD::kCalib:   file = new DataCalib(fPath, fNightAsInt, runid, fDimDrsCalibration, fDimDrsRuns, fMsg); break;
+        case FAD::kNone:    file = new DataDump(fPath, night, runid,  fMsg); break;
+        case FAD::kDebug:   file = new DataDebug(fPath, night, runid, fMsg); break;
+        case FAD::kCfitsio: file = new DataWriteFits(fPath, night, runid,  fMsg); break;
+        case FAD::kFits:    file = new DataWriteFits2(fPath, night, runid, fMsg); break;
+	case FAD::kRaw:     file = new DataWriteRaw(fPath, night, runid, fMsg); break;
+	case FAD::kCalib:   file = new DataCalib(fPath, night, runid, fDimDrsCalibration, fDimDrsRuns, fMsg); break;
         }
 
         try
         {
-            if (!file->Open(h, desc))
-                return 0;
+            // Try to open the file
+            FAD::RunDescription desc;
+            desc.name = evt->runCtrl->runType;
+
+            if (!file->Open(*evt, desc))
+                return false;
         }
         catch (const exception &e)
         {
             fMsg.Error("Exception trying to open file: "+string(e.what()));
-            return 0;
-        }
-
-        fFiles.push_back(file);
+            return false;
+        }
+
+        fLastOpened = runid;
+
+        // Signal that a file is open
+        fFile = shared_ptr<DataProcessorImp>(file);
+
+        // Now do all the calls which potentially block (dim)
+
+        // Time for update runs before time for update events
+        UpdateRuns(file->GetFileName());
+        fNumEvts[kEventId]   = 0;
+        fNumEvts[kTriggerId] = 0;
+        fNumEvts[kCurrent]   = 0;
+        fDimQueue3.post(make_pair(Time(), fNumEvts));
+
+        fDimWriteStats.FileOpened(file->GetFileName());
 
         ostringstream str;
@@ -711,33 +540,16 @@
         fMsg.Info(str);
 
-        fDimWriteStats.FileOpened(file->GetFileName());
-
-        fLastOpened = runid;
-        UpdateRuns(file->GetFileName());
-
-        fNumEvts[kEventId] = 0;
-        fNumEvts[kTriggerId] = 0;
-
-        fNumEvts[kCurrent] = 0;
-        fDimQueue3.post(make_pair(Time(), fNumEvts));
-        // fDimCurrentEvent.Update(uint32_t(0));
-
-        return reinterpret_cast<FileHandle_t>(file);
-    }
-
-    int runWrite(FileHandle_t handler, EVENT *e, size_t /*sz*/)
-    {
-        DataProcessorImp *file = reinterpret_cast<DataProcessorImp*>(handler);
-
-        if (!file->WriteEvt(e))
-            return -1;
-
-        if (file->GetRunId()==fMaxRun)
-        {
-            fNumEvts[kCurrent]++;
-            fNumEvts[kEventId]   = e->EventNum;
-            fNumEvts[kTriggerId] = e->TriggerNum;
-        }
-
+        return true;
+    }
+
+    bool runWrite(const shared_ptr<EVT_CTRL2> &e)
+    {
+        const EVENT &evt = *e->fEvent;
+        if (!fFile->WriteEvt(evt))
+            return false;
+
+        fNumEvts[kCurrent]++;
+        fNumEvts[kEventId]   = evt.EventNum;
+        fNumEvts[kTriggerId] = evt.TriggerNum;
         fNumEvts[kTotal]++;
 
@@ -747,161 +559,47 @@
         {
             fDimQueue3.post(make_pair(Time(), fNumEvts));
-            //fDimEvents.Update(fNumEvts);
             oldt = newt;
         }
 
-
-        // ===> SignalEvtWritten(runid);
-        // Send num events written of newest file
-
-        /* close run runId (all all runs if runId=0) */
-        /* return: 0=close scheduled / >0 already closed / <0 does not exist */
-        //CloseRunFile(file->GetRunId(), time(NULL)+2) ;
-
-        return 0;
+        return true;
+    }
+
+    void runClose()
+    {
+        if (!fFile)
+            return;
+
+        // It can happen that runFinished was never called
+        // (e.g. runWrite failed)
+        if (fRunInProgress==fFile->GetRunId())
+            fRunInProgress = -1;
+
+        // Close the file
+        const bool rc = fFile->Close(NULL);
+
+        fLastClosed = fFile->GetRunId();
+
+        ostringstream str;
+        str << "Closed: " << fFile->GetFileName() << " (" << fFile->GetRunId() << ")";
+        if (!rc)
+            str << "... failed!";
+
+        // Signal that the file is closed
+
+        fFile.reset();
+
+        // Now do all the calls which can potentially block (dim)
+
+        CloseRun(fLastClosed); 
+
+        // Time for update events before time for update runs
+        fDimQueue3.post(make_pair(Time(), fNumEvts));
+        UpdateRuns();
+
+        // Do the potentially blocking call after all others
+        rc ? fMsg.Info(str) : fMsg.Error(str);
     }
 
     virtual void CloseRun(uint32_t /*runid*/) { }
-
-    int runClose(FileHandle_t handler, RUN_TAIL *tail, size_t)
-    {
-        //fMsg.Info(" ==> TODO: Update run configuration in database!");
-
-        DataProcessorImp *file = reinterpret_cast<DataProcessorImp*>(handler);
-
-        const vector<DataProcessorImp*>::iterator it = find(fFiles.begin(), fFiles.end(), file);
-        if (it==fFiles.end())
-        {
-            ostringstream str;
-            str << "File handler (" << handler << ") requested to close by event builder doesn't exist.";
-            fMsg.Fatal(str);
-            return -1;
-        }
-
-        /*
-        fFiles.erase(it);
-
-        fLastClosed = file->GetRunId();
-        CloseRun(fLastClosed);
-        UpdateRuns();
-
-        fDimEvents.Update(fNumEvts);
-        */
-
-        const bool rc = file->Close(tail);
-        if (!rc)
-        {
-            // Error message
-        }
-
-        // Note that this is the signal for the fadctrl to change from
-        // WritingData back to Connected. If this is done too early,
-        // a new run might be started before this is closed. This is
-        // faster, but leads to problems with the DRS calibration
-        // if the system is fast enough to start the new run before
-        // this one has really been closed.
-        fFiles.erase(it);
-
-        fLastClosed = file->GetRunId();
-        CloseRun(fLastClosed);
-        UpdateRuns();
-
-        fDimQueue3.post(make_pair(Time(),fNumEvts));
-        //fDimEvents.Update(fNumEvts);
-
-
-        ostringstream str;
-        str << "Closed: " << file->GetFileName() << " (" << file->GetRunId() << ")";
-        fMsg.Info(str);
-
-        delete file;
-
-        // ==> SignalRunClose(runid);
-        // Send new num open files
-        // Send empty file-name if no file is open
-
-        return rc ? 0 : -1;
-    }
-
-    ofstream fDumpStream[40];
-
-    void debugStream(int isock, void *buf, int len)
-    {
-        if (!fDebugStream)
-            return;
-
-        const int slot = isock/7;
-        if (slot<0 || slot>39)
-            return;
-
-        if (!fDumpStream[slot].is_open())
-        {
-            ostringstream name;
-            name << "socket_dump-" << setfill('0') << setw(2) << slot << ".bin";
-
-            fDumpStream[slot].open(name.str().c_str(), ios::app);
-            if (!fDumpStream[slot])
-            {
-                ostringstream str;
-                str << "Open file '" << name << "': " << strerror(errno) << " (errno=" << errno << ")";
-                fMsg.Error(str);
-
-                return;
-            }
-
-            fMsg.Message("Opened file '"+name.str()+"' for writing.");
-        }
-
-        fDumpStream[slot].write(reinterpret_cast<const char*>(buf), len);
-    }
-
-    ofstream fDumpRead; // Stream to possibly dump docket events
-
-    void debugRead(int isock, int ibyte, uint32_t event, uint32_t ftmevt, uint32_t runno, int state, uint32_t tsec, uint32_t tusec)
-    {
-        //   isock = socketID (0-279)
-        //   ibyte = #bytes gelesen
-        //   event = eventId (oder 0 wenn noch nicht bekannt)
-        //   state : 1=finished reading data
-        //           0=reading data
-        //          -1=start reading data (header)
-        //          -2=start reading data,
-        //             eventId not known yet (too little data)
-        //   tsec, tusec = time when reading seconds, microseconds
-        //
-        if (!fDebugRead || ibyte==0)
-	    return;
-
-        if (!fDumpRead.is_open())
-        {
-            fDumpRead.open("socket_events.txt", ios::app);
-            if (!fDumpRead)
-            {
-                ostringstream str;
-                str << "Open file 'socket_events.txt': " << strerror(errno) << " (errno=" << errno << ")";
-                fMsg.Error(str);
-
-                return;
-            }
-
-            fMsg.Message("Opened file 'socket_events.txt' for writing.");
-
-            fDumpRead << "# START: " << Time().GetAsStr() << endl;
-            fDumpRead << "# state time_sec time_usec socket slot runno event_id trigger_id bytes_received" << endl;
-        }
-
-        fDumpRead
-            << setw(2) << state   << " "
-            << setw(8) << tsec    << " "
-            << setw(9) << tusec   << " "
-            << setw(3) << isock   << " "
-            << setw(2) << isock/7 << " "
-            << runno  << " "
-            << event  << " "
-            << ftmevt << " "
-            << ibyte << endl;
-    }
-
-    array<uint16_t,2> fVecRoi;
 
     void updateRoi(const pair<Time, array<uint16_t,2>> &roi)
@@ -911,17 +609,8 @@
     }
 
-    int eventCheck(uint32_t runNr, PEVNT_HEADER *fadhd, EVENT *event, int /*iboard*/)
-    {
-        /*
-         fadhd[i] ist ein array mit den 40 fad-headers
-         (falls ein board nicht gelesen wurde, ist start_package_flag =0 )
-
-         event  ist die Struktur, die auch die write routine erhaelt;
-         darin sind im header die 'soll-werte' fuer z.B. eventID
-         als auch die ADC-Werte (falls Du die brauchst)
-
-         Wenn die routine einen negativen Wert liefert, wird das event
-         geloescht (nicht an die write-routine weitergeleitet [mind. im Prinzip]
-         */
+    int eventCheck(const shared_ptr<EVT_CTRL2> &evt)
+    {
+        const PEVNT_HEADER *fadhd = evt->FADhead.get();
+        const EVENT *event = evt->fEvent;
 
 	const array<uint16_t,2> roi = {{ event->Roi, event->RoiTM }};
@@ -933,6 +622,6 @@
 	}
 
-        const FAD::EventHeader *beg = reinterpret_cast<FAD::EventHeader*>(fadhd);
-        const FAD::EventHeader *end = reinterpret_cast<FAD::EventHeader*>(fadhd)+40;
+        const FAD::EventHeader *beg = reinterpret_cast<const FAD::EventHeader*>(fadhd);
+        const FAD::EventHeader *end = reinterpret_cast<const FAD::EventHeader*>(fadhd)+40;
 
         // FIMXE: Compare with target configuration
@@ -951,5 +640,5 @@
             {
                 fMsg.Error("Inconsistency in FAD status detected.... closing run.");
-                CloseRunFile(runNr, 0, 0);
+                evt->runCtrl->maxEvt = 0;
                 return -1;
             }
@@ -958,5 +647,5 @@
             {
                 fMsg.Error("Inconsistent run number detected.... closing run.");
-                CloseRunFile(runNr, 0, 0);
+                evt->runCtrl->maxEvt = 0;
                 return -1;
             }
@@ -973,5 +662,5 @@
             {
                 fMsg.Error("Inconsistent FAD event number detected.... closing run.");
-                CloseRunFile(runNr, 0, 0);
+                evt->runCtrl->maxEvt = 0;
                 return -1;
             }
@@ -980,5 +669,5 @@
             {
                 fMsg.Error("Inconsistent FTM trigger number detected.... closing run.");
-                CloseRunFile(runNr, 0, 0);
+                evt->runCtrl->maxEvt = 0;
                 return -1;
             }
@@ -987,5 +676,5 @@
             {
                 fMsg.Error("Inconsistent phase shift detected.... closing run.");
-                CloseRunFile(runNr, 0, 0);
+                evt->runCtrl->maxEvt = 0;
                 return -1;
             }
@@ -994,5 +683,5 @@
             {
                 fMsg.Error("Inconsistent DAC values detected.... closing run.");
-                CloseRunFile(runNr, 0, 0);
+                evt->runCtrl->maxEvt = 0;
                 return -1;
             }
@@ -1001,5 +690,5 @@
             {
                 fMsg.Error("Inconsistent trigger type detected.... closing run.");
-                CloseRunFile(runNr, 0, 0);
+                evt->runCtrl->maxEvt = 0;
                 return -1;
             }
@@ -1014,6 +703,9 @@
     }
 
-    void SendRawData(PEVNT_HEADER *fadhd, EVENT *event)
-    {
+    void applyCalib(const shared_ptr<EVT_CTRL2> &evt)
+    {
+        const PEVNT_HEADER *fadhd = evt->FADhead.get();
+        const EVENT *event = evt->fEvent;
+
         // Currently we send any event no matter what its trigger id is...
         // To be changed.
@@ -1029,6 +721,6 @@
 
         // Workaround to find a valid header.....
-        const FAD::EventHeader *beg = reinterpret_cast<FAD::EventHeader*>(fadhd);
-        const FAD::EventHeader *end = reinterpret_cast<FAD::EventHeader*>(fadhd)+40;
+        const FAD::EventHeader *beg = reinterpret_cast<const FAD::EventHeader*>(fadhd);
+        const FAD::EventHeader *end = reinterpret_cast<const FAD::EventHeader*>(fadhd)+40;
 
         // FIMXE: Compare with target configuration
@@ -1048,5 +740,5 @@
         float *vec = reinterpret_cast<float*>(data.data()+sizeof(EVENT));
 
-        DataCalib::Apply(vec, event->Adc_Data, event->StartPix, event->Roi);
+        evt->runCtrl->calib->Apply(vec, event->Adc_Data, event->StartPix, event->Roi);
         DrsCalibrate::RemoveSpikes(vec, event->Roi);
 
@@ -1068,9 +760,10 @@
         fDimEventData.setQuality(ptr->fTriggerType);
         fDimEventData.Update(data2);
-    }
-
+
+    }
+
+    /*
     void SendFeedbackData(PEVNT_HEADER *fadhd, EVENT *event)
     {
-        /*
         if (!DataCalib::IsValid())
             return;
@@ -1104,27 +797,11 @@
 
         fDimFeedbackData.Update(data2);
-        */
-    }
-
-    int subProcEvt(int threadID, PEVNT_HEADER *fadhd, EVENT *event, int16_t /*iboard*/, void */*buffer*/)
-    {
-        switch (threadID)
-        {
-        case 0:
-            SendRawData(fadhd, event);
-            return 100;
-            /*
-        case 1:
-            SendFeedbackData(fadhd, event);
-            return 2;*/
-        }
-        return 100;
-    }
-
-
-    bool IsRunStarted() const
-    {
-        const set<uint32_t>::const_iterator it = fIsRunStarted.find(fRunNumber-1);
-        return it==fIsRunStarted.end();// ? true : it->second.started;
+    }
+    */
+
+    bool IsRunWaiting()// const
+    {
+        const lock_guard<mutex> lock(mtx_newrun);
+        return fExpectedRuns.find(fRunNumber-1)!=fExpectedRuns.end();
     }
 
@@ -1134,8 +811,9 @@
     }
 
+    /*
     bool IsRunFileOpen()
     {
         return fLastOpened==fRunNumber-1;
-    }
+    }*/
 
     bool IncreaseRunNumber(uint32_t run)
@@ -1159,65 +837,72 @@
     }
 
-    void gotNewRun(uint32_t runnr, PEVNT_HEADER */*headers*/)
-    {
-        // This function is called even when writing is switched off
-        set<uint32_t>::iterator it = fIsRunStarted.begin();
-        while (it!=fIsRunStarted.end())
-        {
-            if (*it<runnr)
+    void gotNewRun(RUN_CTRL2 &run)
+    {
+        // This is to secure iteration over fExpectedRuns
+        const lock_guard<mutex> lock(mtx_newrun);
+
+        map<uint32_t,FAD::RunDescription>::const_iterator it = fExpectedRuns.begin();
+        while (it!=fExpectedRuns.end())
+        {
+            if (it->first<run.runId)
             {
                 ostringstream str;
-                str << "gotNewRun - Missed run " << *it << ".";
+                str << "runOpen - Missed run " << it->first << ".";
                 fMsg.Info(str);
 
-                fIsRunStarted.erase(it++);
+                // Increase the iterator first, it becomes invalid with the next call
+                const auto is = it++;
+                fExpectedRuns.erase(is);
                 continue;
             }
-            if (*it==runnr)
+
+            if (it->first==run.runId)
                 break;
+
             it++;
         }
-        if (it==fIsRunStarted.end())
+
+        if (it==fExpectedRuns.end())
         {
             ostringstream str;
-            str << "gotNewRun - Not waiting for run " << runnr << ".";
+            str << "runOpen - Run " << run.runId << " wasn't expected (maybe manual triggers)";
             fMsg.Warn(str);
-            return;
-        }
-
-        map<uint32_t,FAD::RunDescription>::iterator i2 = fExpectedRuns.find(runnr);
-        if (i2==fExpectedRuns.end())
-        {
-            ostringstream str;
-            str << "gotNewRun - Run " << runnr << " wasn't expected.";
-            fMsg.Warn(str);
-            return;
-        }
-
-        CloseRunFile(runnr, time(NULL)+i2->second.maxtime, i2->second.maxevt);
-        // return: 0=close scheduled / >0 already closed / <0 does not exist
-
-        // FIXME: Move configuration from expected runs to runs which will soon
-        //        be opened/closed
-
-        fIsRunStarted.erase(it);
-    }
-
-    map<boost::thread::id, string> fLastMessage;
-
-    void factOut(int severity, int err, const char *message)
-    {
-        if (!fDebugLog && severity==99)
-            return;
-
+
+            // This is not ideal, but the best we can do
+            run.night = fNightAsInt;
+
+            return;
+        }
+
+        const FAD::RunDescription &conf = it->second;
+
+        run.runType   = conf.name;
+        run.maxEvt    = conf.maxevt;
+        run.closeTime = conf.maxtime + run.openTime;
+        run.night     = conf.night;
+
+        fExpectedRuns.erase(it);
+
+        // Now signal the fadctrl (configuration process that a run is in progress)
+        // Maybe this could be done earlier, but we are talking about a
+        // negligible time scale here.
+        fRunInProgress = run.runId;
+    }
+
+    void runFinished()
+    {
+        // This is called when the last event of a run (run time exceeded or
+        // max number of events exceeded) has been received.
+        fRunInProgress = -1;
+    }
+
+    //map<boost::thread::id, string> fLastMessage;
+
+    void factOut(int severity, const char *message)
+    {
         ostringstream str;
-        //str << boost::this_thread::get_id() << " ";
-        str << "EventBuilder(";
-        if (err<0)
-            str << "---";
-        else
-            str << err;
-        str << "): " << message;
-
+        str << "EventBuilder: " << message;
+
+        /*
         string &old = fLastMessage[boost::this_thread::get_id()];
 
@@ -1225,4 +910,5 @@
             return;
         old = str.str();
+        */
 
         fMsg.Update(str, severity);
@@ -1266,9 +952,4 @@
     */
 
-    void factStat(const EVT_STAT &/*stat*/)
-    {
-        //fDimStatistics2.Update(stat);
-    }
-
     void factStatSend(const pair<Time,GUI_STAT> &stat)
     {
@@ -1309,5 +990,5 @@
             arr[i] = *ref;
 
-            if (gi_NumConnect[i]!=7)
+            if (gi_NumConnect[i]==0)
             {
                 arr[i] = 0;
@@ -1357,5 +1038,5 @@
             vec[i+2] = *ref;
 
-            if (gi_NumConnect[i]!=7)
+            if (gi_NumConnect[i]==0)
             {
                 vec[i+2] = 0;
@@ -1382,5 +1063,4 @@
     void Update(DimDescribedService &svc, const array<T, N> &data, const Time &t=Time(), int n=N)
     {
-//        svc.setQuality(vec[40]<=vec[41]);
         svc.setData(const_cast<T*>(data.data()), sizeof(T)*n);
         svc.Update(t);
@@ -1524,5 +1204,5 @@
     }
 
-    void debugHead(int /*socket*/, const FAD::EventHeader &h)
+    void debugHead(const FAD::EventHeader &h)
     {
         const uint16_t id = h.Id();
@@ -1540,7 +1220,4 @@
 
         fDimQueue2.post(make_tuple(Time(), changed, h));
-
-        //const lock_guard<mutex> guard(fMutexDimQueue2);
-        //fDimQueue2.push_back(make_tuple(Time(), changed, h));
     }
 };
@@ -1549,90 +1226,61 @@
 
 // ----------- Event builder callbacks implementation ---------------
-extern "C"
+bool runOpen(const shared_ptr<EVT_CTRL2> &evt)
 {
-    FileHandle_t runOpen(uint32_t irun, RUN_HEAD *runhd, size_t len)
-    {
-        return EventBuilderWrapper::This->runOpen(irun, runhd, len);
-    }
-
-    int runWrite(FileHandle_t fileId, EVENT *event, size_t len)
-    {
-        return EventBuilderWrapper::This->runWrite(fileId, event, len);
-    }
-
-    int runClose(FileHandle_t fileId, RUN_TAIL *runth, size_t len)
-    {
-        return EventBuilderWrapper::This->runClose(fileId, runth, len);
-    }
-
-    // -----
-
-    //void *runStart(uint32_t /*irun*/, RUN_HEAD */*runhd*/, size_t /*len*/)
-    //{
-    //    return NULL;
-    //}
-
-    int subProcEvt(int threadID, PEVNT_HEADER *fadhd, EVENT *event, int16_t mboard, void *runPtr)
-    {
-        return EventBuilderWrapper::This->subProcEvt(threadID, fadhd, event, mboard, runPtr);
-    }
-
-    int runEnd(uint32_t, void */*runPtr*/)
-    {
-        return 0;
-    }
-
-    // -----
-
-    int eventCheck(uint32_t runNr, PEVNT_HEADER *fadhd, EVENT *event, int mboard)
-    {
-        return EventBuilderWrapper::This->eventCheck(runNr, fadhd, event, mboard);
-    }
-
-    void gotNewRun(uint32_t runnr, PEVNT_HEADER *headers)
-    {
-        return EventBuilderWrapper::This->gotNewRun(runnr, headers);
-    }
-
-    // -----
-
-    void factOut(int severity, int err, const char *message)
-    {
-        EventBuilderWrapper::This->factOut(severity, err, message);
-    }
-
-    void factStat(GUI_STAT stat)
-    {
-        EventBuilderWrapper::This->factStat(stat);
-    }
-
-    void factStatNew(EVT_STAT stat)
-    {
-        EventBuilderWrapper::This->factStat(stat);
-    }
-
-    void factReportIncomplete (uint64_t rep)
-    {
-        EventBuilderWrapper::This->factReportIncomplete(rep);
-    }
-
-    // ------
-
-    void debugHead(int socket, int/*board*/, void *buf)
-    {
-        const FAD::EventHeader &h = *reinterpret_cast<FAD::EventHeader*>(buf);
-        EventBuilderWrapper::This->debugHead(socket, h);
-    }
-
-    void debugStream(int isock, void *buf, int len)
-    {
-        return EventBuilderWrapper::This->debugStream(isock, buf, len);
-    }
-
-    void debugRead(int isock, int ibyte, int32_t event, int32_t ftmevt, int32_t runno, int state, uint32_t tsec, uint32_t tusec)
-    {
-        EventBuilderWrapper::This->debugRead(isock, ibyte, event, ftmevt, runno, state, tsec, tusec);
-    }
+    return EventBuilderWrapper::This->runOpen(evt);
 }
 
+bool runWrite(const shared_ptr<EVT_CTRL2> &evt)
+{
+    return EventBuilderWrapper::This->runWrite(evt);
+}
+
+void runClose()
+{
+    EventBuilderWrapper::This->runClose();
+}
+
+int eventCheck(const shared_ptr<EVT_CTRL2> &evt)
+{
+    return EventBuilderWrapper::This->eventCheck(evt);
+}
+
+void gotNewRun(RUN_CTRL2 &run)
+{
+    EventBuilderWrapper::This->gotNewRun(run);
+}
+
+void runFinished()
+{
+    EventBuilderWrapper::This->runFinished();
+}
+
+void applyCalib(const shared_ptr<EVT_CTRL2> &evt)
+{
+    EventBuilderWrapper::This->applyCalib(evt);
+}
+
+void factOut(int severity, const char *message)
+{
+    EventBuilderWrapper::This->factOut(severity, message);
+}
+
+void factStat(GUI_STAT stat)
+{
+    EventBuilderWrapper::This->factStat(stat);
+}
+
+void factReportIncomplete(uint64_t rep)
+{
+    EventBuilderWrapper::This->factReportIncomplete(rep);
+}
+
+// ------
+
+void debugHead(void *buf)
+{
+    const FAD::EventHeader &h = *reinterpret_cast<FAD::EventHeader*>(buf);
+    EventBuilderWrapper::This->debugHead(h);
+}
+
 #endif
