Back Midas Rome Roody Rootana
  Midas DAQ System, Page 134 of 137  Not logged in ELOG logo
ID Date Author Topicdown Subject
  70   17 Jan 2004 Stefan Ritt First try- midas on darwin/macosx
> With the ALIGN8() change ODB works, mhttpd works. ALIGN8 change now commited to cvs, verified that "make all" builds 
> on Linux.

Verified that "make all" still works under Windows.

> ROOT stuff still blows up because of more namespace pollution (/usr/include/sys/something does #define Free(x) 
> free(blah...)). Arguably, it is not Apple's fault- portable programs should not include any <sys/foo.h> header files. I 
> think I can fix it by moving "#include <sys/mount.h>" from midasinc.h to system.h.

I would like to keep all OS specific #includes in midasinc.h. In worst case put another section there for OSX, like

in midas.h:

#if !defined(OS_MACOSX)
#if defined ( __????__ ) <- put the proper thing here
#define OS_MACOSX
#endif
#endif

then make a new seciton in midasinc.h

#ifdef OS_MACOSX
#include <...>
#endif

> Also figured out why PVM is defined- more pollution from "#include <sys/blah...>". This is only in mana.c and I will 
> repace every "#ifdef PVM" with "#ifdef HAVE_PVM". Is there documentation that should be updated as well? Alternatively I 
> can try to play games with header files...

Right, PVM should be replaced by HAVE_PVM. This is only for the analyzer. I planned at some point to run the analyzer in 
parallel on a linux cluster, but it was never really used. Going to ROOT, that facility should be replaces by PROOF.

> Then, a new problem- on MacOSX, pthread_t is not an "INT" and system.c:ss_thread_create() whines about it. I want to 
> introduce a system dependant THREAD_T (or whatever) and make ss_thread_create() return that, rather than INT.

Good. If you have a OS_MACOSX, that should help you there.

-SR
  8   17 Jan 2004 Stefan Ritt Access to hardware in the MIDAS framework
> The result is strange because the get function is called all the time very 
> fast (much faster then the 9 seconds as set in the equipment) and even 
> before starting the run (I just put the flag RO_RUNNING).

This is on purpose. When the frontend is idle, it loops over the slow control 
equipment as fast as possible. This way, you see changes in your hardware very 
quickly. I see no reason to waste CPU cycles in the frontend when there are 
better things to do like reading slow control equipment. Presume you have the 
alarm system running, which turns off some equipment in case of an over 
current. You better do this as quickly as possible, not wasting up to 9 
seconds each time.

The 9 seconds you mention are for reading *EVENTS*. You have double 
functionality: First, reading the slow control system, writing updated values 
to the ODB, where someone else can display or evaluate them (in the alarm 
system for example). Second, assemble events and sending them with the other 
data to disk or tape. Only the second one gets controlled by RO_RUNNING and 
the 9 seconds. You can see this by the updating event statists on your 
frontend display, which increments only when running and then every 9 seconds.
  71   18 Jan 2004 Konstantin Olchanski First try- midas on darwin/macosx
> I would like to keep all OS specific #includes in midasinc.h

No go. Here is the problem:

midasinc.h includes sys/mount.h, which #defines Free(x) to be something else
mana.c includes msystem.h, which includes midasinc.h
mana.c includes ROOT header files, which blow up because Free(x) is redefined.

I want this:

mana.c does *not* include sys/mount.h
system.c does include sys/mount.h

Simplest solution is to take sys/mount.h out of midasinc.h and include it in system.c

> Right, PVM should be replaced by HAVE_PVM.

Commited.

> > Then, a new problem- on MacOSX, pthread_t is not an "INT" and system.c:ss_thread_create() whines about it. I want to 
> > introduce a system dependant THREAD_T (or whatever) and make ss_thread_create() return that, rather than INT.
> Good. If you have a OS_MACOSX, that should help you there.

Okey. In Darwin, pthread_t is not an int. It is a pointer to a struct. In midas.c I typedef midas_pthread_t to HANDLE on Windows and to pthread_t n OS_UNIX.

This uncovered a problem with ss_getthandle(). What is it supposed to do? On Windows it returns a handle to the current thread, on OS_UNIX, it returns getpid(). 
What gives? I am leaving it alone for now.

Attached is the current diff. Most changes are in system.c: ss_timezone() and midas_pthread_t. The Makefile part is already commited. Building the shared 
library was made dependant on NEED_SHLIB. Now, building static midas applications is very simple, use "make SHLIB="

K.O.
Attachment 1: xxx
? .ALARM.SHM
? .ELOG.SHM
? .ODB.SHM
? .SYSMSG.SHM
? darwin
? midas.log
? xx
? xxx
Index: Makefile
===================================================================
RCS file: /usr/local/cvsroot/midas/Makefile,v
retrieving revision 1.50
diff -r1.50 Makefile
0a1
> 
218a220,224
> #
> # Uncomment the next line to build the midas shared library
> #
> NEED_SHLIB=1
> 
268a275,290
> # MacOSX/Darwin is just a funny Linux
> #
> ifeq ($(OSTYPE),Darwin)
> OSTYPE = darwin
> endif
> 
> ifeq ($(OSTYPE),darwin)
> OS_DIR = darwin
> OSFLAGS = -DOS_LINUX -DOS_DARWIN -DHAVE_STRLCPY -fPIC -Wno-unused-function
> LIBS = -lpthread
> SPECIFIC_OS_PRG = $(BIN_DIR)/mlxspeaker
> NEED_RANLIB=1
> NEED_SHLIB=
> endif
> 
> #-----------------------
340a363,364
> LIB    =$(LIBNAME)
> ifdef NEED_SHLIB
342,344c366,367
< LIB =   -lmidas
< # Uncomment this for static linking of midas executables
< #LIB =   $(LIBNAME)
---
> LIB   = $(SHLIB)
> endif
351c374
< 	$(LIB_DIR)/fal.o $(PROGS)
---
>  	$(LIB_DIR)/fal.o $(PROGS)
431a455,457
> ifdef NEED_RANLIB
> 	ranlib $@
> endif
432a459
> ifdef NEED_SHLIB
435a463
> endif
Index: include/midas.h
===================================================================
RCS file: /usr/local/cvsroot/midas/include/midas.h,v
retrieving revision 1.126
diff -r1.126 midas.h
464c464
< #if defined(OS_LINUX) || defined(OS_OSF1) || defined(OS_ULTRIX) || defined(OS_FREEBSD) || defined(OS_SOLARIS) || defined(OS_IRIX)
---
> #if defined(OS_LINUX) || defined(OS_OSF1) || defined(OS_ULTRIX) || defined(OS_FREEBSD) || defined(OS_SOLARIS) || defined(OS_IRIX) || defined(OS_DARWIN)
534a535,544
> #endif
> 
> /* need system-dependant thread type */
> #if defined(OS_WINNT)
> typedef HANDLE midas_thread_t;
> #elif defined(OS_UNIX)
> #include <pthread.h>
> typedef pthread_t midas_thread_t;
> #else
> typedef INT midas_thread_t;
Index: include/midasinc.h
===================================================================
RCS file: /usr/local/cvsroot/midas/include/midasinc.h,v
retrieving revision 1.11
diff -r1.11 midasinc.h
50a51
> #include <assert.h>
157d157
< #include <sys/mount.h>
163a164,165
> #ifdef OS_DARWIN
> #else
164a167
> #endif
166a170,172
> #ifdef OS_DARWIN
> #include <util.h>
> #else
167a174
> #endif
Index: include/msystem.h
===================================================================
RCS file: /usr/local/cvsroot/midas/include/msystem.h,v
retrieving revision 1.37
diff -r1.37 msystem.h
719,720c719,720
<    INT EXPRT ss_thread_create(INT(*func) (void *), void *param);
<    INT EXPRT ss_thread_kill(INT thread_id);
---
>    midas_thread_t EXPRT ss_thread_create(INT(*func) (void *), void *param);
>    INT EXPRT ss_thread_kill(midas_thread_t thread_id);
721a722
>    INT ss_timezone(void);
Index: src/mhttpd.c
===================================================================
RCS file: /usr/local/cvsroot/midas/src/mhttpd.c,v
retrieving revision 1.262
diff -r1.262 mhttpd.c
6983c6983
<    x_act = (int) floor((double) (xmin - timezone) / label_dx) * label_dx + timezone;
---
>    x_act = (int) floor((double) (xmin - ss_timezone()) / label_dx) * label_dx + ss_timezone();
6995,6996c6995,6996
<          if ((x_act - timezone) % major_dx == 0) {
<             if ((x_act - timezone) % label_dx == 0) {
---
>          if ((x_act - ss_timezone()) % major_dx == 0) {
>             if ((x_act - ss_timezone()) % label_dx == 0) {
Index: src/system.c
===================================================================
RCS file: /usr/local/cvsroot/midas/src/system.c,v
retrieving revision 1.78
diff -r1.78 system.c
306a307,310
> #ifdef OS_UNIX
> #include <sys/mount.h>
> #endif
> 
895c899
<     INT              thread handle
---
>     INT thread handle
914c918
<    return (int) hThread;
---
>    return hThread;
1653c1657
< thread_id = ss_thread_spawn((void *) taskWatch, &tsWatch);
---
> midas_thread_t thread_id = ss_thread_create((void *) taskWatch, &tsWatch);
1662c1666
< thread_id = ss_thread_spawn((void *) taskWatch, pDevice);
---
> midas_thread_t thread_id = ss_thread_create((void *) taskWatch, pDevice);
1673c1677
< INT ss_thread_create(INT(*thread_func) (void *), void *param)
---
> midas_thread_t ss_thread_create(INT(*thread_func) (void *), void *param)
1675c1679
< #ifdef OS_WINNT
---
> #if defined(OS_WINNT)
1689,1690c1693
< #endif                          /* OS_WINNT */
< #ifdef OS_MSDOS
---
> #elif defined(OS_MSDOS)
1694,1695c1697
< #endif                          /* OS_MSDOS */
< #ifdef OS_VMS
---
> #elif defined(OS_VMS)
1699c1701
< #endif                          /* OS_VMS */
---
> #elif defined(OS_VXWORKS)
1701d1702
< #ifdef OS_VXWORKS
1719d1719
< #endif                          /* OS_VXWORKS */
1721c1721,1722
< #ifdef OS_UNIX
---
> #elif defined(OS_UNIX)
> 
1728c1729,1730
< #endif                          /* OS_UNIX */
---
> 
> #endif
1738c1740
< thread_id = ss_thread_create((void *) taskWatch, pDevice);
---
> midas_thread_t thread_id = ss_thread_create((void *) taskWatch, pDevice);
1749c1751
< INT ss_thread_kill(INT thread_id)
---
> INT ss_thread_kill(midas_thread_t thread_id)
1751c1753
< #ifdef OS_WINNT
---
> #if defined(OS_WINNT)
1755c1757
<    status = TerminateThread((HANDLE) thread_id, 0);
---
>    status = TerminateThread(thread_id, 0);
1759,1760c1761
< #endif                          /* OS_WINNT */
< #ifdef OS_MSDOS
---
> #elif defined(OS_MSDOS)
1764,1765c1765
< #endif                          /* OS_MSDOS */
< #ifdef OS_VMS
---
> #elif defined(OS_VMS)
1769c1769
< #endif                          /* OS_VMS */
---
> #elif defined(OS_VXWORKS)
1771d1770
< #ifdef OS_VXWORKS
1773d1771
< 
1775d1772
< 
1777d1773
< #endif                          /* OS_VXWORKS */
1779,1782c1775
< #ifdef OS_UNIX
<    INT status;
< 
<    status = pthread_kill((pthread_t) thread_id, SIGKILL);
---
> #elif defined(OS_UNIX)
1783a1777,1778
>    INT status;
>    status = pthread_kill(thread_id, SIGKILL);
1785c1780,1781
< #endif                          /* OS_UNIX */
---
> 
> #endif
2339c2335
< #ifdef OS_WINNT
---
> #if defined(OS_WINNT)
2356,2357c2352,2358
< #endif
< #ifdef OS_UNIX
---
> #elif defined(OS_DARWIN)
> 
>    assert(!"ss_settime() is not supported");
>    /* not reached */
>    return SS_NO_DRIVER;
> 
> #elif defined(OS_UNIX)
2361,2362c2362
< #endif
< #ifdef OS_VXWORKS
---
> #elif defined(OS_VXWORKS)
2411a2412,2438
> INT ss_timezone()
> /********************************************************************\
> 
>   Routine: ss_timezone
> 
>   Purpose: Returns what?!?
> 
>   Input:
>     none
> 
>   Output:
>     what the heck does it return?!?
> 
>   Function value:
>     INT what is it?!?
> 
> \********************************************************************/
> {
> #ifdef OS_DARWIN
>   return 0;
> #else
>   return timezone; /* on Linux, comes from "#include <time.h>". What is it ?!? */
> #endif
> }
> 
> 
> /*------------------------------------------------------------------*/
4850c4877
<    INT status;
---
> #if defined(OS_DARWIN)
4852c4879,4883
< #ifdef OS_UNIX
---
>    return 0;
> 
... 14 more lines ...
  72   19 Jan 2004 Stefan Ritt First try- midas on darwin/macosx
> I want this:
> 
> mana.c does *not* include sys/mount.h
> system.c does include sys/mount.h
> 
> Simplest solution is to take sys/mount.h out of midasinc.h and include it in system.c

Agree.

> This uncovered a problem with ss_getthandle(). What is it supposed to do? On Windows it returns a handle to the current thread, on OS_UNIX, it returns getpid(). 
> What gives? I am leaving it alone for now.

The Unix version of ss_getthandle() returns the pid since at the time when I wrote that function (many years ago) there were no threads under Unix. It should now 
be replaces with a function which returns the real thread id (at least under Linux).
  73   19 Jan 2004 Konstantin Olchanski First try- midas on darwin/macosx
> > Simplest solution is to take sys/mount.h out of midasinc.h and include it in system.c
> Agree.

Done.

With this, I commited the rest of my changes: midas_thread_t in midas.h, change ss_thread_xxx() prototypes in msystem.h
, implementation in system.c

My cvs diff is now empty.

Midas should compile on Darwin aka macosx, I tested "odbedit" and "mhttpd"- they seem to work.
 
> > This uncovered a problem with ss_getthandle(). 
> The Unix version of ss_getthandle() returns the pid since at the time when I wrote that function (many years ago) there were no threads under Unix. It should now 
> be replaces with a function which returns the real thread id (at least under Linux).

I do not want to touch this. Sorry.

K.O.
  66   19 Jan 2004 Konstantin Olchanski darwin aka macosx changes
I commited the final bits to make Midas build on Darwin aka macosx.

Here is the summary:

1) I treat Darwin as a funny linux, so OS_LINUX is always defined
2) OS_DARWIN is defined for places where the two differ
3) system dependant directory is "midas/darwin/{bin,lib}"
4) a few header files had to be moved around to dodge namespace pollution by Apple system 
header files (i.e. one of the PowerPC header files #defines PVM- collision with PVM in mana.c, 
another #defines Free(x)- collision with ROOT header files)
5) ss_thread_create() and ss_thread_kill() now use midas_thread_t. On Darwin ptherad_t is not 
an "int".
6) the Makefile has no support for building the midas shared library on macosx.
7) on my Mac OS 10.2.8 machine, "make all" works, "odbedit" and "mhttpd" run. This is the 
full extent of my testing. Status on Mac OS 10.3.x is unknown.

K.O.
  9   10 Mar 2004 Jan Wouters Creation of secondary Midas output file.
Dear Midas Team,

I have run into a problem with Midas and was wondering if you could explain what I 
am doing wrong.  I have included a simple demo to illustrate what I am doing and 
can send a small input data file if needed.

WHAT I AM TRYING TO DO:
Every midas event for the DANCE experiment consists of many physics events.  I am 
trying to create a secondary mid file where the event boundaries are now the 
physics events rather than the midas events.  This secondary mid file will be 
analyzed using a second stage midas analyzer.

For the demo, I use the data from EV02 (one of our 15 frontends), which consists of a 
variable number of fixed length structures where each structure contains the data for 
one crystal from the DANCE detector. 
 I treat each crystal as a separate physics event and write it out in the TREK bank, 
which is a demo calculated output bank, as a separate event.   

(The only difference between this demo and our real system is that we would include 
all the crystals from the other frontends that have approximately the same time stamp 
in the output bank.  Thus the output bank would consist of a varing number of 
crystals in one event rather than the fixed one crystal per event used in this demo.)

THE CHANGES TO analyzer.c AND adccalib.c
I loop through the EV02 bank examining each crystal structure in turn.  I calculate 
"calibrated" parameters and put them into an output bank called TREK.  The unusual 
part of this example is that the TREK bank is no longer part of the main list of input 
banks, ana_trigger_bank_list[].   Instead it is now part of a new bank list called 
ana_physics_bank_list[].  See the analyzer.c file for this definition.

In adccalib.c I  create the space for this new bank as follows. 

	EVENT_HEADER 	gPhysicsEventHeaders[ MAX_EVENT_SIZE / sizeof( 
EVENT_HEADER ) ];  
	WORD* 		gPhysicsEventData = ( WORD * )( gPhysicsEventHeaders + 1 );		

In the adc_calib routine I create the bank header as follows.  Note that the serial 
numbers will restart at 0 at the beginning of each midas event.  Should I let the serial 
number increment monotonically until the end of the run?:

	gPhysicsEventHeaders->serial_number = (DWORD) - 1;
	gPhysicsEventHeaders->event_id = 2;
	gPhysicsEventHeaders->trigger_mask = 0;
	gPhysicsEventHeaders->time_stamp = pheader->time_stamp;

In a loop that loops through all the crystals contained in EV02,  I extract each crystal, 
calibrate it, and store it in a TREK structure.  In creating the TREK bank I assume that 
each one will be a separate physics event thus I update the event serial number and 
use bk_init32 to initialize the memory.   

   	for ( short i = 0; i < nItems; i++ )
  	{	++(gPhysicsEventHeaders->serial_number);  	// Update serial number.
  		bk_init32( gPhysicsEventData );		// Initialize storage.
  		bk_create( gPhysicsEventData, "TREK", TID_STRUCT, &trek );
  	
  		trek->one = (double) pev->areahg * 1.0;
  		trek->two = (float) pev->timelo * 1.0;

  		bk_close( gPhysicsEventData, trek+1 );
  		
  		pev++; 					// Loop to next crystal's data. 
	}	

The output bank should consist of multiple events for each individual EV02 midas 
input event. 

 As far as I can tell the code compiles and runs fine, but I get no data in the .mid 
output file except for the ODB. I have a print statement at the beginning of each 
midas event stating how many crystals were found in the EV02 bank.  I also print out 
the calibrated value for each crystal as it is being placed in its own TREK output 
bank.  The data appears correct.

 I cannot place TREK in the input bank the way it normally is done in the examples 
because there is not a one-to-one correspondence between a midas event and a 
true physics event.  Instead one midas event has many physics events.  Thus the 
output bank needs to be in a new memory area so that I can create a custom header 
and increment the serial number properly for each event.  Our follow-on analysis 
using a second Midas analyzer only needs to analyze one physics event at a time 
rather than one Midas event at a time, which is why we are going to all the trouble to 
get this paradigm working.

I include all the code for this very simple example. 

RUNNING THE CODE:
To run the example just use the run01220.mid file I will send:

./analyzer -i run01220.mid.gz -o run01220out.mid -c settings.odb_cfg -n 50

The only thing done by the settings.odb_cfg file is to turn on the TREK output bank.  I 
have verified that the bank is on.

SUMMARY:
I believe that I must not be creating the new TREK output bank correctly so that 
midas understands that the event-by-event calculated physics data should be written 
out event-by-event.  I have pointed out several places in the above discussion where 
I might be making a mistake.

I would like to get both this example running and a similar which create Root trees, 
though the Root trees are of secondary importance.  With this example I can finish 
writing the second stage analyzer and get the DANCE collaboration moving forward 
with their analysis.  Currently, we cannot use this paradigm because I cannot create 
a secondary mid file in our stage one analysis.  I would be very grateful if you could 
take a look at this example and tell me what I am doing incorrectly.

Jan
Attachment 1: dance193.tar
  10   10 Mar 2004 Stefan Ritt Creation of secondary Midas output file.
Dear Jan,

I had a look at your code. You create a gPhysicsEventHeader array, fill it, and expect the 
framework to write it to disk. But how can the framework "guess" that you want your private 
global array being written? Unfortunately it cannot do magic!

Do do what you want, you have to write a "secondary" midas file yourself. I modified your 
code to do that. First, I define the event storage like

BYTE           gSecEvent[ MAX_EVENT_SIZE ];
EVENT_HEADER   *gPhysicsEventHeader = (EVENT_HEADER *) gSecEvent;
WORD* 	       gPhysicsEventData = ( WORD * )( gPhysicsEventHeader + 1 );		

I use gSecEvent as a BYTE array, since it only contains one avent at a time, so this is more 
appropriate. Then, in the BOR routine, I open a file:

  sprintf(str, "sec%05d.mid", run_number);
  sec_fh = open(str, O_CREAT | O_RDWR | O_BINARY, 0644);

and close it in the EOR routine

  close(sec_fh);

The event routine now manually fills events into the secondary file:

      /* write event to secondary .mid file */
      gPhysicsEventHeader->data_size = bk_size(gPhysicsEventData);
      write(sec_fh, gPhysicsEventHeader, sizeof(EVENT_HEADER)+bk_size(gPhysicsEventData));

Note that this code is placed *inside* the for() loop over nItems, so for each detector you 
create and event and write it.

That's all you need, the full file adccalib.c is attached. I tried to produce a sec01220.mid 
file and was able to read it back with the mdump utility.

Best regards,

  Stefan
Attachment 1: adccalib.c
/********************************************************************\

  Name:         adccalib.c
  Created by:   Stefan Ritt

  Contents:     Example analyzer module for ADC calibration. Looks
                for ADC0 bank, subtracts pedestals and applies gain
                calibration. The resulting values are appended to 
                the event as an CADC bank ("calibrated ADC"). The
                pedestal values and software gains are stored in
                adccalib_param structure which was defined in the ODB
                and transferred to experim.h.

\********************************************************************/
                                                    
/*-- Include files -------------------------------------------------*/

/* standard includes */
#include <stdio.h>
#include <time.h>
#include <io.h>
#include <fcntl.h>

/* midas includes */
#include "midas.h"
#include "experim.h"
#include "analyzer.h"

/* root includes */
#include <TH1F.h>
#include <TTree.h>
#include <TDirectory.h>

/* Local stuff, struct for handling analysis demo...
   using EV01_BANK as template for bank mapping */
#define N_STRUCT_ELEMENT 6
#define N_FRONTENDS 14

/* Histo info, could be placed in ODB */
typedef struct {
    char name[ 256 ];
    char title[ 256 ];
    INT  nbins;
    float xlow;
    float xhigh; 
} EV_HI_DEF;

EV_HI_DEF h[ N_STRUCT_ELEMENT ]={
    {"AreaHG", "AreaHG"   , 1024, 0.0, 1023.},
    {"AreaLG", "AreaLG"   , 1024, 0.0, 1023.},
    {"TimeHi", "Time High", 1024, 0.0, 1023.},
    {"TimeLo", "Time Low" , 1024, 0.0, 1023.},
    {"Detid" , "Detector ID" , 1024, 0.0, 1023.},
    {"Slope" , "Slope"    , 1024, 0.0, 1023.}
};

/*-- Parameters ----------------------------------------------------*/
/* local creation of ODB struct */
GAMMA_PARAM_STR( gamma_param_str );
GAMMA_PARAM gamma_param;

/* Global ODB struct (taken care by analyzer.c) */
extern EXP_PARAM      exp_param;
extern RUNINFO        runinfo;

/*-- Module declaration --------------------------------------------*/
INT adc_calib( EVENT_HEADER*, void* );
INT adc_calib_init( void );
INT adc_calib_bor( INT run_number );
INT adc_calib_eor( INT run_number );

/*-- New Bank Area -------------------------------------------------*/
BYTE           gSecEvent[ MAX_EVENT_SIZE ];
EVENT_HEADER 	*gPhysicsEventHeader = (EVENT_HEADER *) gSecEvent;
					// Trick used for allocating MAX_EVENT_SIZE bytes for bank.
WORD* 			gPhysicsEventData = ( WORD * )( gPhysicsEventHeader + 1 );		
					// Pointer to start of first data record

/* file for secondary .mid file */
int sec_fh;

/* The module name "Gamma" is used for the ODB tree under
   /Analyzer/Parameters. It maps the experim.h gamma struct.
*/

ANA_MODULE adc_calib_module = {
  "Gamma",                       /* module name           */  
  "Pierre",                      /* author                */
  adc_calib,                     /* event routine         */
  adc_calib_bor,                 /* BOR routine           */
  adc_calib_eor,                 /* EOR routine           */
  adc_calib_init,                /* init routine          */
  NULL,                          /* exit routine          */
  &gamma_param,                  /* parameter structure   */
  sizeof(gamma_param),           /* structure size        */
  gamma_param_str,               /* initial parameters    */
};

/*-- module-local variables ----------------------------------------*/

extern TDirectory *gManaHistsDir;

/* Root Histo objects */
static TH1F* gAdcHists[ N_FRONTENDS ];

/*-- init routine --------------------------------------------------*/

#define TM_N_BINS  2048
#define TM_X_LOW      0
#define TM_X_HIGH  40000

INT adc_calib_init(void)
{
  char name[ 256 ];
  int fe_number = 2;
  int  i;
  char title[256];

  // Some booking for demo
  // Just book the crystals from frontend 2.
  for (i=0; i < N_STRUCT_ELEMENT; i++)
  {
    sprintf(name, "%s-%2.2i" , h[i].name, fe_number);
    sprintf(title, "%s-%2.2i", h[i].title, fe_number);
    
    gAdcHists[i] = (TH1F*)gManaHistsDir->GetList()->FindObject(name);
    printf("Booking Histo:%s\n", name);

    if (gAdcHists[i] == NULL)
      gAdcHists[i] = new TH1F(name, title, h[i].nbins, h[i].xlow, h[i].xhigh);
  }
  
  return SUCCESS;
}

/*-- BOR routine ---------------------------------------------------*/

INT adc_calib_bor(INT run_number)
{
char str[80];

  sprintf(str, "sec%05d.mid", run_number);
  sec_fh = open(str, O_CREAT | O_RDWR | O_BINARY, 0644);
  if (sec_fh < 0)
     cm_msg(MERROR, "adc_calib_bor", "Cannot open secondary .mid file \"%s\"", str);

  return SUCCESS;
}

/*-- eor routine ---------------------------------------------------*/

INT adc_calib_eor(INT run_number)
{
  close(sec_fh);
  return SUCCESS;
}

/*-- event routine -------------------------------------------------*/

INT adc_calib(EVENT_HEADER *pheader, void *pevent)
{
  	INT      	n_items;
  	DWORD   	*pdata;
  	EV01_BANK *pev;
  	TREK_BANK *trek;
  
// Initialize the calculate output bank including the header.
	gPhysicsEventHeader->serial_number = (DWORD) - 1;
	gPhysicsEventHeader->event_id = 2;
	gPhysicsEventHeader->trigger_mask = 0;
	gPhysicsEventHeader->time_stamp = pheader->time_stamp;

// For demo assume each crystal in bank 2 is new event.  This really isn't 
// true, but it is analogous to splitting one midas event into multiple physics 
// events.

/* Get there with ID = 1 -> EVxx,  
   For demo histo EV02 EV_BANK all elements.

	Create a new bank TREK which is a structure bank.
	We are testing the breaking of a single midas event
	into individual physics events.  Thus we will take
	each crystal in EV02 and make it a separate event
	in the TREK output bank.
	
   	[local:Default:S]Bank switches>set TREK 1
   	for output

   Apply some calibration from the gamma ODB struct.
*/

/* look for EV02 bank, return if not present, skip TMxx ....
   n_items: number of elements in the bank */
  	if ( !( n_items = bk_locate( pevent, "EV02", &pdata ) ) )
    	return 1;

// Loop through all items in bank.

	short nItems =  n_items/ sizeof( EV01_BANK );
	printf( "Number of bytes %d, number of items %d\n", n_items, nItems );
	 	
  	pev = (EV01_BANK *)pdata;
  	for ( short i = 0; i < nItems; i++ )
  	{
  
  /* fill histos not really elegant for now*/
  		gAdcHists[0]->Fill((float) pev->areahg, 1);
  		gAdcHists[1]->Fill((float) pev->arealg, 1);
  		gAdcHists[2]->Fill((float) pev->timehi, 1);
  		gAdcHists[3]->Fill((float) pev->timelo, 1);
  		gAdcHists[4]->Fill((float) pev->detid, 1);
  		gAdcHists[5]->Fill((float) pev->slop, 1);
  
  // create calibrated TREK bank.  Recall that this output bank mimics
  // the splitting up of the midas bank into physics events.
  		++(gPhysicsEventHeader->serial_number);  	// Update serial number.
  		bk_init32( gPhysicsEventData );				// Initialize storage.
  		bk_create( gPhysicsEventData, "TREK", TID_STRUCT, &trek );
  	
  		trek->one = (double) pev->areahg * 1.0;
  		trek->two = (float) pev->timelo * 1.0;

  		printf("area: %e time: %f\n", trek->one, trek->two );

  		bk_close( gPhysicsEventData, trek+1 );
  		
  		pev++; // Loop to next crystal's data.  	
  
      
      /* write event to secondary .mid file */
      gPhysicsEventHeader->data_size = bk_size(gPhysicsEventData);
      write(sec_fh, gPhysicsEventHeader, sizeof(EVENT_HEADER)+bk_size(gPhysicsEventData));
  	}


  /* close calculated bank */
  return SUCCESS;
}
  11   11 Mar 2004 Renee Poutissou Creation of secondary Midas output file.
Jan , 

Do you need to log this stage 1 output?  If not, you would use the 
eventbuilder mechanism to create your stage 2 events.  
I use the eventbuilder mechanism with success for my TWIST experiment.

Renee
  64   30 Mar 2004 Konstantin Olchanski elog fixes
I am about to commit the mhttpd Elog fixes we have been using in TWIST since
about October. The infamous Elog "last N days" problem is fixed, sundry
memory overruns are caught and assert()ed.

For the curious, the "last N days" problem was caused by uninitialized data
in the elog handling code. A non-zero-terminated string was read from a file
and passed to atoi(). Here is a simplifed illustration:

char str[256]; // uninitialized, filled with whatever happens on the stack
read(file,str,6); // read 6 bytes, non-zero terminated
// str now looks like this: "123456UUUUUUUUU....", "U" is uninitialized memory
int len = atoi(str); // if the first "U" happens to be a number, we lose.

The obvious fix is to add "str[6]=0" before the atoi() call.

Attached is the CVS diff for the proposed changes. Please comment.

K.O.
Attachment 1: elog-fixes.txt
Index: src/midas.c
===================================================================
RCS file: /usr/local/cvsroot/midas/src/midas.c,v
retrieving revision 1.203
diff -u -r1.203 midas.c
--- src/midas.c	19 Mar 2004 09:58:22 -0000	1.203
+++ src/midas.c	31 Mar 2004 05:11:00 -0000
@@ -14814,8 +14814,9 @@
 \********************************************************************/
 
 /********************************************************************/
-void el_decode(char *message, char *key, char *result)
+void el_decode(char *message, char *key, char *result, int size)
 {
+   char *rstart = result;
    char *pc;
 
    if (result == NULL)
@@ -14828,6 +14829,8 @@
          *result++ = *pc++;
       *result = 0;
    }
+
+   assert(strlen(rstart) < size);
 }
 
 /**dox***************************************************************/
@@ -15020,9 +15023,9 @@
          size = atoi(str + 9);
          read(fh, message, size);
 
-         el_decode(message, "Date: ", date);
-         el_decode(message, "Thread: ", thread);
-         el_decode(message, "Attachment: ", attachment);
+         el_decode(message, "Date: ", date, sizeof(date));
+         el_decode(message, "Thread: ", thread, sizeof(thread));
+         el_decode(message, "Attachment: ", attachment, sizeof(attachment));
 
          /* buffer tail of logfile */
          lseek(fh, 0, SEEK_END);
@@ -15092,7 +15095,7 @@
       sprintf(message + strlen(message), "========================================\n");
       strcat(message, text);
 
-      assert(strlen(message) < sizeof(message));        // bomb out on array overrun.
+      assert(strlen(message) < sizeof(message)); /* bomb out on array overrun. */
 
       size = 0;
       sprintf(start_str, "$Start$: %6d\n", size);
@@ -15104,6 +15107,9 @@
          sprintf(tag, "%02d%02d%02d.%d", tms->tm_year % 100, tms->tm_mon + 1,
                  tms->tm_mday, (int) TELL(fh));
 
+      /* size has to fit in 6 digits */
+      assert(size < 999999);
+
       sprintf(start_str, "$Start$: %6d\n", size);
       sprintf(end_str, "$End$:   %6d\n\f", size);
 
@@ -15339,13 +15345,20 @@
          return EL_FILE_ERROR;
       }
 
-      if (strncmp(str, "$End$: ", 7) == 0) {
-         size = atoi(str + 7);
-         lseek(*fh, -size, SEEK_CUR);
-      } else {
+      if (strncmp(str, "$End$: ", 7) != 0) {
          close(*fh);
          return EL_FILE_ERROR;
       }
+        
+      /* make sure the input string to atoi() is zero-terminated:
+       * $End$:      355garbage
+       * 01234567890123456789 */
+      str[15] = 0;
+
+      size = atoi(str + 7);
+      assert(size > 15);
+
+      lseek(*fh, -size, SEEK_CUR);
 
       /* adjust tag */
       sprintf(strchr(tag, '.') + 1, "%d", (int) TELL(*fh));
@@ -15364,14 +15377,21 @@
       }
       lseek(*fh, -15, SEEK_CUR);
 
-      if (strncmp(str, "$Start$: ", 9) == 0) {
-         size = atoi(str + 9);
-         lseek(*fh, size, SEEK_CUR);
-      } else {
+      if (strncmp(str, "$Start$: ", 9) != 0) {
          close(*fh);
          return EL_FILE_ERROR;
       }
 
+      /* make sure the input string to atoi() is zero-terminated
+       * $Start$:    606garbage
+       * 01234567890123456789 */
+      str[15] = 0;
+
+      size = atoi(str+9);
+      assert(size > 15);
+
+      lseek(*fh, size, SEEK_CUR);
+
       /* if EOF, goto next day */
       i = read(*fh, str, 15);
       if (i < 15) {
@@ -15444,7 +15464,7 @@
 
 \********************************************************************/
 {
-   int size, fh, offset, search_status;
+   int size, fh = 0, offset, search_status, rd;
    char str[256], *p;
    char message[10000], thread[256], attachment_all[256];
 
@@ -15462,10 +15482,24 @@
 
    /* extract message size */
    offset = TELL(fh);
-   read(fh, str, 16);
-   size = atoi(str + 9);
+   rd = read(fh, str, 15);
+   assert(rd == 15);
+   
+   /* make sure the input string is zero-terminated before we call atoi() */
+   str[15] = 0;
+
+   /* get size */
+   size = atoi(str+9);
+   
+   assert(strncmp(str,"$Start$:",8) == 0);
+   assert(size > 15);
+   assert(size < sizeof(message));
+   
    memset(message, 0, sizeof(message));
-   read(fh, message, size);
+
+   rd = read(fh, message, size);
+   assert(rd > 0);
+   assert((rd+15 == size)||(rd == size));
 
    close(fh);
 
@@ -15473,14 +15507,14 @@
    if (strstr(message, "Run: ") && run)
       *run = atoi(strstr(message, "Run: ") + 5);
 
-   el_decode(message, "Date: ", date);
-   el_decode(message, "Thread: ", thread);
-   el_decode(message, "Author: ", author);
-   el_decode(message, "Type: ", type);
-   el_decode(message, "System: ", system);
-   el_decode(message, "Subject: ", subject);
-   el_decode(message, "Attachment: ", attachment_all);
-   el_decode(message, "Encoding: ", encoding);
+   el_decode(message, "Date: ",     date,     80); /* size from show_elog_submit_query() */
+   el_decode(message, "Thread: ", thread, sizeof(thread));
+   el_decode(message, "Author: ",   author,   80); /* size from show_elog_submit_query() */
+   el_decode(message, "Type: ",     type,     80); /* size from show_elog_submit_query() */
+   el_decode(message, "System: ",   system,   80); /* size from show_elog_submit_query() */
+   el_decode(message, "Subject: ",  subject, 256); /* size from show_elog_submit_query() */
+   el_decode(message, "Attachment: ", attachment_all, sizeof(attachment_all));
+   el_decode(message, "Encoding: ", encoding, 80); /* size from show_elog_submit_query() */
 
    /* break apart attachements */
    if (attachment1 && attachment2 && attachment3) {
@@ -15496,6 +15530,10 @@
                strcpy(attachment3, p);
          }
       }
+
+      assert(strlen(attachment1) < 256); /* size from show_elog_submit_query() */
+      assert(strlen(attachment2) < 256); /* size from show_elog_submit_query() */
+      assert(strlen(attachment3) < 256); /* size from show_elog_submit_query() */
    }
 
    /* conver thread in reply-to and reply-from */
  65   30 Mar 2004 Stefan Ritt elog fixes
Thanks for fixing these long lasting bugs. The code is much cleaner now, please
commit it.
  62   28 Apr 2004 Konstantin Olchanski mhttpd "start run" input field length?
I am setting up a new experiment and I added a "comment" field to "/
Experiment/Edit on start". When I start the run, I see this field, but I
cannot enter anything: the HTML "maxlength" is zero (or 1?). I traced this
to mhttpd.c: if (this is a string) maxlength = key.item_size. But what is
key.item_size for a string? The current length? If so, how do I enter a
string that is longer than the current one (zero in case I start from
scratch). I am stumped! K.O.
  63   30 Apr 2004 Stefan Ritt mhttpd
> I am setting up a new experiment and I added a "comment" field to "/
> Experiment/Edit on start". When I start the run, I see this field, but I
> cannot enter anything: the HTML "maxlength" is zero (or 1?). I traced this
> to mhttpd.c: if (this is a string) maxlength = key.item_size. But what is
> key.item_size for a string? The current length? If so, how do I enter a
> string that is longer than the current one (zero in case I start from
> scratch). I am stumped! K.O.

Your problem is that you created a ODB string with zero length. If you do this
through ODBEdit, a default length of 32 is used:

[local:Test:S]Edit on start>cr string Comment
String length [32]:
[local:Test:S]Edit on start>ls -l
Key name                        Type    #Val  Size  Last Opn Mode Value
---------------------------------------------------------------------------
Comment                         STRING  1     32    2s   0   RWD
[local:Test:S]Edit on start>

which then results in a maxlength of 32 as well during run start. I presume
you used mhttpd itself to create the string. Trying to reporduce this, I found
that mhttpd creates strings with zero length. I will fix this soon. Until
then, use ODBEdit to create your strings.
  58   07 May 2004 Konstantin Olchanski min(a,b) in mana.c and mlogger.c
When I compile current cvs-head midas, I get errors about undefined function
min(). I do not think min() is in the list of standard C functions, so
something else should be used instead, like a MIN(a,b) macro. To make life
more interesting, in a few places, there is also a variable called "min".
Here is the error:

src/mana.c: In function `INT write_event_ascii(FILE*, EVENT_HEADER*, 
   ANALYZE_REQUEST*)':
src/mana.c:2571: `min' undeclared (first use this function)
src/mana.c:2571: (Each undeclared identifier is reported only once for each 
   function it appears in.)
make: *** [linux/lib/rmana.o] Error 1

K.O.
  59   07 May 2004 Stefan Ritt min(a,b) in mana.c and mlogger.c
> When I compile current cvs-head midas, I get errors about undefined function
> min(). I do not think min() is in the list of standard C functions, so
> something else should be used instead, like a MIN(a,b) macro. To make life
> more interesting, in a few places, there is also a variable called "min".
> Here is the error:
> 
> src/mana.c: In function `INT write_event_ascii(FILE*, EVENT_HEADER*, 
>    ANALYZE_REQUEST*)':
> src/mana.c:2571: `min' undeclared (first use this function)
> src/mana.c:2571: (Each undeclared identifier is reported only once for each 
>    function it appears in.)
> make: *** [linux/lib/rmana.o] Error 1

This is really a miracle to me. The min/max macros are defined both in midas.h
and msystem.h and worked the last ten years or so. However, I agree that macros
should follow the standard and use capital letters, so I changed that.
  61   06 Jun 2004 Konstantin Olchanski Makefile: set -rpath
I commited Makefile bits to set the RPATH on dynamically linked executables
to find libmidas.so and ROOT shared libraries without setting
LD_LIBRARY_PATH , etc. K.O.
  60   21 Jun 2004 Piotr Zolnierczuk min(a,b) in mana.c and mlogger.c
> > When I compile current cvs-head midas, I get errors about undefined function
> > min(). I do not think min() is in the list of standard C functions, so
> > something else should be used instead, like a MIN(a,b) macro. To make life
> > more interesting, in a few places, there is also a variable called "min".
> > Here is the error:
> > 
> > src/mana.c: In function `INT write_event_ascii(FILE*, EVENT_HEADER*, 
> >    ANALYZE_REQUEST*)':
> > src/mana.c:2571: `min' undeclared (first use this function)
> > src/mana.c:2571: (Each undeclared identifier is reported only once for each 
> >    function it appears in.)
> > make: *** [linux/lib/rmana.o] Error 1
> 
> This is really a miracle to me. The min/max macros are defined both in midas.h
> and msystem.h and worked the last ten years or so. However, I agree that macros
> should follow the standard and use capital letters, so I changed that.

The problem is that /usr/include/c++/3.*/bits/stl_algobase.h contains 
#undef min
#undef max

and in C++ with STL one should really use something like this
    std::min<INT>(a,b)


Cheers
  Piotr
  12   21 Jun 2004 Piotr Zolnierczuk FAQ: anonymous cvs access?
Is the midas CVS server set-up so that I can pull the newest 
version off the CVS server?

What would be my CVSROOT?
pserver:anoncvs@midas.psi.ch:/cvs/midas *this did not work* :)

Piotr

 
  13   21 Jun 2004 Pierre-André Amaudruz FAQ: anonymous cvs access?
> Is the midas CVS server set-up so that I can pull the newest 
> version off the CVS server?
> 
> What would be my CVSROOT?
> pserver:anoncvs@midas.psi.ch:/cvs/midas *this did not work* :)
> 
> Piotr
> 
>  

In the Midas doc under "Quick Start"
http://midas.triumf.ca/doc/html/quickstart.html
you will find the proper cvs command for accessing the latest cvs Midas
version. The public pwd is cvs. You will only be able to checkout/update the
package.
  51   22 Jun 2004 Exaos Lee How to compile under Darwin-gcc? (MacOS X)
I add the following to makefile and try to treat Darwin as FreeBSD/Linux.
But I failed.
============ 
#-----------------------
# This is for MacOS X
#
ifeq ($(OSTYPE), Darwin)
CC = gcc
OS_DIR = Darwin
OSFLAGS = -DOS_DARWIN -DOS_LINUX
LIBS = -lbsd -lcompat
SPECIFIC_OS_PRG =
endif
============

I got the following errors:
=============
gcc -c -g -O2 -Wall -Iinclude -Idrivers -LDarwin/lib -DINCLUDE_FTPLIB  
-DOS_DARWIN -DOS_FREEBSD -o Darwin/lib/midas.o src/midas.c
In file included from include/midasinc.h:45,
                 from include/msystem.h:114,
                 from src/midas.c:623:
/usr/include/string.h:112: error: conflicting types for `strlcat'
include/midas.h:1701: error: previous declaration of `strlcat'
/usr/include/string.h:113: error: conflicting types for `strlcpy'
include/midas.h:1700: error: previous declaration of `strlcpy'
In file included from include/msystem.h:114,
                 from src/midas.c:623:
include/midasinc.h:161:21: sys/vfs.h: No such file or directory
include/midasinc.h:164:17: pty.h: No such file or directory
src/midas.c:780: error: conflicting types for `dbg_malloc'
include/midas.h:1478: error: previous declaration of `dbg_malloc'
src/midas.c:817: error: conflicting types for `dbg_calloc'
include/midas.h:1479: error: previous declaration of `dbg_calloc'
src/midas.c:858: error: conflicting types for `strlcpy'
/usr/include/string.h:113: error: previous declaration of `strlcpy'
src/midas.c:892: error: conflicting types for `strlcat'
/usr/include/string.h:112: error: previous declaration of `strlcat'
gmake: *** [Darwin/lib/midas.o] Error 1
==========

Could anyone give me some hints. Thanks!
ELOG V3.1.4-2e1708b5