ybos.c

Go to the documentation of this file.
00001 /*  Copyright (c) 1993      TRIUMF Data Acquistion Group
00002  *  Please leave this header in any reproduction of that distribution
00003  *
00004  *  TRIUMF Data Acquisition Group, 4004 Wesbrook Mall, Vancouver, B.C. V6T 2A3
00005  *  Email: online@triumf.ca         Tel: (604) 222-1047    Fax: (604) 222-1074
00006  *         amaudruz@triumf.ca                            Local:           6234
00007  * ---------------------------------------------------------------------------
00008    $Log: ybos.c,v $
00009    Revision 1.60  2004/09/29 17:57:11  midas
00010    Added large file (>2GB) support for linux
00011 
00012    Revision 1.59  2004/01/13 00:51:36  pierre
00013    fix dox comment for vxworks
00014 
00015    Revision 1.58  2004/01/08 08:40:11  midas
00016    Implemented standard indentation
00017 
00018    Revision 1.57  2004/01/08 06:35:25  pierre
00019    Doxygen the file
00020 
00021    Revision 1.56  2003/10/30 14:17:07  midas
00022    Added 'umask' for FTP connections
00023 
00024    Revision 1.55  2003/10/03 19:00:45  pierre
00025    fix event display format
00026 
00027    Revision 1.54  2003/06/12 19:19:13  pierre
00028    handle TID_STRUCT bank type (->8bit)
00029 
00030    Revision 1.53  2003/05/17 22:37:48  pierre
00031    ybos large file fix
00032 
00033    Revision 1.52  2003/04/23 23:09:30  pierre
00034    Fixed compiler warning
00035 
00036    Revision 1.51  2003/04/17 16:53:35  pierre
00037    fix tape return code for WINNT
00038 
00039    Revision 1.50  2003/04/16 05:45:21  pierre
00040    fix EOD return , add -DLARGEFILE64_SOURCE support
00041 
00042    Revision 1.49  2003/04/15 22:24:56  pierre
00043    fix for compilation with -Wall
00044 
00045    Revision 1.48  2003/04/11 18:56:47  pierre
00046    Made file compile under VC++ 5.0
00047 
00048    Revision 1.47  2003/04/10 15:51:18  pierre
00049    remove bk_find
00050 
00051    Revision 1.46  2003/04/10 15:45:45  pierre
00052    Made file compile under C++
00053 
00054    Revision 1.45  2002/09/18 16:37:55  pierre
00055    remove bk_list()
00056 
00057    Revision 1.44  2002/08/29 22:12:16  pierre
00058    WORD casting for evt display
00059 
00060    Revision 1.43  2002/08/02 19:42:30  pierre
00061    ifdef vxWorks all the logger & mdump functions
00062 
00063    Revision 1.42  2002/07/14 00:19:59  pierre
00064    add DSP_UNK, fix YB_DONE
00065 
00066    Revision 1.41  2002/07/12 19:31:41  pierre
00067    deallocation error in yb_any_file_rclose
00068 
00069    Revision 1.40  2002/06/10 22:51:27  pierre
00070    fix undefined types
00071 
00072    Revision 1.39  2002/06/08 06:05:22  pierre
00073    improve mdump display format
00074 
00075    Revision 1.38  2002/05/28 17:34:19  pierre
00076    Fix bug for large events (bigger than 8192 bytes), Renee Poutissou
00077 
00078    Revision 1.37  2002/05/08 19:54:41  midas
00079    Added extra parameter to function db_get_value()
00080 
00081    Revision 1.36  2002/03/05 01:17:24  pierre
00082    Add default case, TID_SBYTE
00083 
00084    Revision 1.35  2002/03/05 01:04:37  pierre
00085    add TID_SHORT for display
00086 
00087    Revision 1.34  2001/12/12 17:52:19  pierre
00088    1.8.3-2 doc++
00089 
00090    Revision 1.33  2001/11/09 20:28:16  pierre
00091    Fix replay for YBOS format
00092 
00093    Revision 1.32  2001/09/14 17:04:57  pierre
00094    fix gzread for Midas fmt
00095 
00096    Revision 1.31  2001/07/20 20:38:26  pierre
00097    -Make ybk_close_... return bank size in bytes
00098    -Fix replay (mdump) when file size less than 32K (fmt=midas)
00099 
00100    Revision 1.30  2001/04/30 19:58:03  pierre
00101    - fix ybk_iterate for return -1 instead of 0 (empty bank possible)
00102 
00103    Revision 1.29  2000/09/28 13:11:21  midas
00104    Fixed compiler warning
00105 
00106    Revision 1.28  2000/07/21 18:27:32  pierre
00107    - Include YBOS version >4.0 support by default, otherwise use in Makefile
00108      -DYBOS_VERSION_3_3 for MIDAS_PREF_FLAGS
00109 
00110    Revision 1.27  2000/05/04 14:50:12  midas
00111    Return yb_tid_size[] via new function ybos_get_tid_size()
00112 
00113    Revision 1.26  2000/04/26 19:10:25  pierre
00114    -Moved first round of doc++ comments from ybos.h to here
00115 
00116    Revision 1.25  2000/02/25 18:53:48  pierre
00117    - fix typo in function name dm_()
00118 
00119    Revision 1.24  2000/01/25 18:57:07  pierre
00120    - fix midas replay end of file
00121 
00122    Revision 1.23  1999/12/20 22:15:53  pierre
00123    - remove #define INCLUDE_FTP due to VxWorks (moved into Makefile)
00124 
00125    Revision 1.22  1999/12/17 19:49:01  pierre
00126    - fix return event length in ybos_event_get
00127 
00128    Revision 1.21  1999/12/13 23:26:40  pierre
00129    - Active FTP for YBOS format (yb_any_file_wopen)
00130    - Remove printf dbg in ybos_write()
00131 
00132    Revision 1.20  1999/09/30 22:56:46  pierre
00133    - Change TID_DOUBLE, D8_BKTYPE display format
00134    - fix return yb_any_swap
00135 
00136    Revision 1.19  1999/09/29 20:41:21  pierre
00137    - several fixes for bk32, added TID_DOUBLE display.
00138 
00139    Revision 1.18  1999/09/24 00:13:43  pierre
00140    - include bk32 option
00141    - Fix some pointers
00142 
00143    Revision 1.17  1999/07/24 00:41:54  pierre
00144    - Fix midas_physrec_get(void **prec, ...) for lazylogger
00145 
00146    Revision 1.16  1999/07/23 07:04:54  midas
00147    Fixed compiler warnings
00148 
00149    Revision 1.15  1999/07/22 19:06:07  pierre
00150    - Added D8_BKTYPE for Ybos
00151    - Fix long event for MIDAS
00152    - Allow FIXED event display in raw format
00153 
00154    Revision 1.14  1999/06/23 09:43:02  midas
00155    Added ftp functionality (for lazylogger)
00156 
00157    Revision 1.13  1999/02/11 13:18:58  midas
00158    Fixed bug in opening disk file under NT
00159 
00160    Revision 1.12  1999/01/22 09:29:51  midas
00161    Fixed typo with braces
00162 
00163    Revision 1.11  1999/01/20 08:39:19  midas
00164    Fixed even more compiler warnings
00165 
00166    Revision 1.10  1999/01/19 19:58:06  pierre
00167    - Fix several compiler warnings
00168 
00169    Revision 1.9  1999/01/18 17:42:59  pierre
00170    - Added lost cvs log flag
00171 
00172  *
00173  *  Description : ybos.c : contains support for the YBOS structure.
00174  *              : YBOS is a 4bytes aligned structure. The FIRST element
00175  *                of a YBOS event is always the LRL (Logical Record Length)
00176  *                This element represent the event size in 4 bytes count!
00177  *            
00178  *                The event structure is the following 
00179  *                        Midas event        Ybos event
00180  *         pheader ->     EVENT_HEADER      EVENT_HEADER      
00181  *         pmbkh   ->     BANK_HEADER           LRL             <- plrl
00182  *                        BANK              YBOS_BANK_HEADER    <- pybk
00183  *
00184  *                pevent is used for yb_any_....() pointing to pheader for MIDAS
00185  *                                                 pointing to plrl    for YBOS
00186  *                All ybk_...() requires plrl as input pointer
00187  *                All  bk_...() requires pmbkh as input pointer
00188  *
00189  *                While replaying data, the EVENT_HEADER has been striped out
00190  *                from the event in the YBOS format. In this case the plrl is the
00191  *                first data of the event. NO MORE EVENT_HEADER is present. In order
00192  *                to provide anyway some evnt info, The FE could produce a EVID bank
00193  *                containing a "copy" of the EVENT_HEADER (see ybos_simfe.c)
00194  *                If the EVID is present in the YBOS event, mdump will try to recover 
00195  *                this info and display it.
00196  *
00197  *                function marked with * are externaly accessible
00198  *
00199  *   Section a)*: bank manipulation.
00200  *                ybk_init
00201  *                ybk_create, ybk_create_chaos
00202  *                ybk_close, ybk_close_chaos
00203  *                ybk_size, ybk_list, ybk_find, ybk_locate, ybk_iterate
00204  *   Section b) : mlogger functions.
00205  *                *ybos_log_open,      *ybos_write,      *ybos_log_close
00206  *                ybos_log_dump,       ybos_buffer_flush 
00207  *                ybos_logfile_close,  ybos_logfile_open, 
00208  *   Section c)   utilities (mdump, lazylogger, etc...)
00209  *                *yb_any_file_ropen,   *yb_any_file_rclose (uses my struct)
00210  *                *yb_any_file_wopen    *yb_any_file_wclose
00211  *                *yb_any_physrec_get:   ybos_physrec_get
00212  *                                       midas_physrec_get
00213  *                yb_any_dev_os_read,  yb_any_dev_os_write
00214  *                *yb_any_log_write
00215  *                *yb_any_physrec_skip:  ybos_physrec_skip
00216  *                *yb_any_physrec_display
00217  *                *yb_any_all_info_display
00218  *                *yb_any_event_swap:    ybos_event_swap
00219  *                *yb_any_event_get:     ybos_event_get
00220  *                                       midas_event_get
00221  *                *yb_any_event_display: yb_any_raw_event_display
00222  *                                       yb_any_bank_event_display
00223  *                *yb_any_bank_display:  yb_any_raw_bank_display
00224  *                                       ybos_bank_display
00225  *                                       midas_bank_display
00226  *   Section d)   File fragmentation and recovery
00227  *                *feodb_file_dump:    yb_file_fragment
00228  *                *yb_file_recompose : yb_ymfile_open
00229  *                                     yb_ymfile_update
00230  *
00231  *                gz not tested
00232  *                ftp channel not tested
00233  *
00234 
00235  *          online replay MIDAS YBOS NT UNIX TAPE DISK FTP largeEVT frag/recomp
00236  *                
00237  */
00238 
00239 /**dox***************************************************************/
00240 /** @file ybos.c
00241 The YBOS file
00242 */
00243 
00244 /**dox***************************************************************/
00245 /** @defgroup ybosbankc YBOS Bank Functions (ybk_xxx)
00246  */
00247 
00248 /**dox***************************************************************/
00249 /** @addtogroup ybosincludecode
00250  *  
00251  *  @{  */
00252 
00253 /**dox***************************************************************/
00254 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00255 
00256 
00257 /* include files */
00258 /* moved #define INCLUDE_FTPLIB into makefile (!vxWorks) */
00259 
00260 #define TRACE
00261 #include "midas.h"
00262 #include "msystem.h"
00263 
00264 #ifdef INCLUDE_FTPLIB
00265 #include "ftplib.h"
00266 #endif
00267 
00268 #ifdef INCLUDE_ZLIB
00269 #include "zlib.h"
00270 #endif
00271 
00272 #define INCLUDE_LOGGING
00273 #include "ybos.h"
00274 
00275 INT yb_tid_size[] = {
00276    0,                           /* 0 not defined */
00277    2,                           /* 1 integer *2 */
00278    1,                           /* 2 ASCII bytes */
00279    4,                           /* 3 Integer *4 */
00280    4,                           /* 4 float *4 */
00281    8,                           /* 5 double */
00282    0,                           /* 6 undefined */
00283    0,                           /* 7 undefined */
00284    1,                           /* 8 logical*1 */
00285 };
00286 
00287 /*---- Hidden prototypes ---------------------------------------------------*/
00288 /* File fragmentation and recovery */
00289 INT yb_any_dev_os_read(INT handle, INT type, void *prec, DWORD nbytes, DWORD * nread);
00290 INT yb_any_dev_os_write(INT handle, INT type, void *prec, DWORD nbytes, DWORD * written);
00291 INT yb_ymfile_update(int slot, int fmt, void *pevt);
00292 INT yb_ymfile_open(int *slot, int fmt, void *pevt, char *svpath, INT file_mode);
00293 INT yb_file_fragment(EQUIPMENT * eqp, EVENT_HEADER * pevent, INT run_number, char *path);
00294 
00295 INT midas_event_skip(INT evtn);
00296 INT ybos_physrec_skip(INT bl);
00297 
00298 INT ybos_physrec_get(DWORD ** prec, DWORD * readn);
00299 INT midas_physrec_get(void *prec, DWORD * readn);
00300 
00301 void yb_any_bank_event_display(void *pevent, INT data_fmt, INT dsp_fmt);
00302 void yb_any_raw_event_display(void *pevent, INT data_fmt, INT dsp_fmt);
00303 
00304 void yb_any_raw_bank_display(void *pbank, INT data_fmt, INT dsp_fmt);
00305 void ybos_bank_display(YBOS_BANK_HEADER * pybk, INT dsp_fmt);
00306 void midas_bank_display(BANK * pbk, INT dsp_fmt);
00307 void midas_bank_display32(BANK32 * pbk, INT dsp_fmt);
00308 
00309 INT ybos_event_get(DWORD ** plrl, DWORD * size);
00310 INT midas_event_get(void **pevent, DWORD * size);
00311 INT ybos_event_swap(DWORD * pevt);
00312 
00313 INT ybos_buffer_flush(LOG_CHN * log_chn, INT run_number);
00314 INT ybos_logfile_open(INT type, char *path, HNDLE * handle);
00315 INT ybos_logfile_close(INT type, HNDLE handle);
00316 void ybos_log_dump(LOG_CHN * log_chn, short int event_id, INT run_number);
00317 
00318 /* MAGTA parameters for YBOS disk file
00319    When the disk file has a *BOT record at the BOF then,
00320    VMS can read nicely the file. YBOS package knows how to
00321    deal with this too. The format in I*4 is then:
00322    0x00000004 (record length in bytes)
00323    0x544f422a (the record content "*BOT")
00324    0x7ff8 (record length in bytes)
00325    0x1ffd x 0x00000000 (empty record)
00326    0x7ff8 (record length in bytes)
00327    0x1ffd x user data
00328    0x7ff8 (record length in bytes)
00329    0x1ffd x user data
00330    :
00331    :
00332    */
00333 
00334 #ifdef INCLUDE_FTPLIB
00335 FTP_CON *ftp_con;
00336 #endif
00337 
00338 /* magta stuff */
00339 DWORD *pbot, *pbktop = NULL;
00340 char *ptopmrd;
00341 DWORD magta[3] = { 0x00000004, 0x544f422a, 0x00007ff8 };
00342 
00343 /* For Fragmentation */
00344 R_YM_FILE ymfile[MAX_YM_FILE];
00345 struct stat *filestat;
00346 
00347 #ifdef INCLUDE_ZLIB
00348 gzFile filegz;
00349 #endif
00350 
00351 /* General YBOS/MIDAS struct for util */
00352 struct {
00353    INT handle;                  /* file handle */
00354    char name[MAX_FILE_PATH];    /* Device name (/dev/nrmt0h) */
00355 
00356    char *pmp;                   /* ptr to a physical TAPE_BUFFER_SIZE block */
00357    EVENT_HEADER *pmh;           /* ptr to Midas event (midas bank_header) */
00358    EVENT_HEADER *pme;           /* ptr to Midas content (event+1) (midas bank_header) */
00359    char *pmrd;                  /* current point in the phyical record */
00360 
00361    char *pmagta;                /* dummy zone for magta stuff */
00362    YBOS_PHYSREC_HEADER *pyh;    /* ptr to ybos physical block header */
00363    DWORD *pylrl;                /* ptr to ybos logical record */
00364    DWORD *pyrd;                 /* ptr to current loc in physical record */
00365 
00366    DWORD evtn;                  /* current event number */
00367    DWORD serial;                /* serial event number */
00368    DWORD evtlen;                /* current event length (-1 if not available) */
00369    DWORD size;                  /* ybos block size or midas max_evt_size */
00370    DWORD recn;                  /* ybos current physical record number */
00371    INT fmt;                     /* contains FORMAT type */
00372    INT type;                    /* Device type (tape, disk, ...) */
00373    DWORD runn;                  /* run number */
00374    BOOL zipfile;
00375    BOOL magtafl;
00376 } my;
00377 
00378 /**dox***************************************************************/
00379 #endif                          /* DOXYGEN_SHOULD_SKIP_THIS */
00380 
00381 /**dox***************************************************************/
00382 /** @addtogroup ybosbankc
00383  *  
00384  *  @{  */
00385 
00386 /*--BANK MANIPULATION-----Section a)--------------------------------*/
00387 /*--BANK MANIPULATION-----------------------------------------------*/
00388 /*--BANK MANIPULATION-----------------------------------------------*/
00389 /*--BANK MANIPULATION-----------------------------------------------*/
00390 /*--BANK MANIPULATION-----------------------------------------------*/
00391 /*--BANK MANIPULATION-----------------------------------------------*/
00392 /*------------------------------------------------------------------*/
00393 /*------------------------------------------------------------------*/
00394 /*------------------------------------------------------------------*/
00395 /********************************************************************/
00396 /**
00397 Initializes an event for YBOS banks structure.
00398 
00399 Before banks can be created in an event, ybk_init()
00400 has to be called first.  See @ref YBOS_bank_examples.
00401 @param plrl    pointer to the first DWORD of the event area of event 
00402 @return void
00403 */
00404 void ybk_init(DWORD * plrl)
00405 {
00406    *plrl = 0;
00407    return;
00408 }
00409 
00410 /**dox***************************************************************/
00411 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00412 
00413 static YBOS_BANK_HEADER *__pbkh;
00414 
00415 /**dox***************************************************************/
00416 #endif                          /* DOXYGEN_SHOULD_SKIP_THIS */
00417 
00418 /********************************************************************/
00419 /**
00420 Define the following memory area to be a YBOS bank with the
00421 given attribute.  See @ref YBOS_bank_examples.
00422 
00423 Before banks can be created in an event, ybk_init(). 
00424 has to be called first. YBOS does not support mixed bank type. i.e: all the
00425 data are expected to be of the same type. YBOS is a 4 bytes bank aligned structure.
00426 Padding is performed at the closing of the bank (see ybk_close) with values of
00427 0x0f or/and 0x0ffb. See @ref YBOS_bank_examples.
00428 @param plrl   pointer to the first DWORD of the event area.
00429 @param bkname name to be assigned to the breated bank (max 4 char)
00430 @param bktype @ref YBOS_Bank_Types of the values for the entire created bank.
00431 @param pbkdat return pointer to the first empty data location.
00432 @return void
00433 */
00434 void ybk_create(DWORD * plrl, char *bkname, DWORD bktype, void *pbkdat)
00435 {
00436    DWORD dname = 0;
00437    __pbkh = (YBOS_BANK_HEADER *) (((DWORD *) (plrl + 1)) + (*(DWORD *) plrl));
00438    strncpy((char *) &dname, bkname, 4);
00439    __pbkh->name = *((DWORD *) bkname);
00440    __pbkh->number = 1;
00441    __pbkh->index = 0;
00442    __pbkh->length = 0;
00443    __pbkh->type = bktype;
00444    *((DWORD **) pbkdat) = (DWORD *) (__pbkh + 1);
00445    return;
00446 }
00447 
00448 /**dox***************************************************************/
00449 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00450 
00451 static DWORD *__pchaosi4;
00452 
00453 /********************************************************************/
00454 void ybk_create_chaos(DWORD * plrl, char *bkname, DWORD bktype, void *pbkdat)
00455 /********************************************************************\
00456 Routine: ybk_create
00457 Purpose: fills up the bank header,
00458 reserve the first 4bytes for the size of the bank in bt unit
00459 and return the pointer to the user space.
00460 Input:
00461 DWORD * pevt          pointer to the top of the YBOS event (LRL)
00462 char  * bname         Bank name should be char*4
00463 DWORD   bktype            Bank type can by either
00464 I2_BKTYPE, I1_BKTYPE, I4_BKTYPE, F4_BKTYPE
00465 Output:
00466 void    *pbkdat       pointer to first valid data of the created bank
00467 Function value:
00468 none
00469 \********************************************************************/
00470 {
00471    DWORD dname = 0;
00472    __pbkh = (YBOS_BANK_HEADER *) ((plrl + 1) + (*plrl));
00473    strncpy((char *) &dname, bkname, 4);
00474    __pbkh->name = *((DWORD *) bkname);
00475    __pbkh->number = 1;
00476    __pbkh->index = 0;
00477    __pbkh->length = 0;
00478    __pbkh->type = bktype;
00479 
00480    *((DWORD **) pbkdat) = (DWORD *) (__pbkh + 1);
00481    __pchaosi4 = (DWORD *) (*(DWORD *) pbkdat);
00482    *((DWORD **) pbkdat) += 1;
00483    return;
00484 }
00485 
00486 /*------------------------------------------------------------------*/
00487 INT ybk_close_chaos(DWORD * plrl, DWORD bktype, void *pbkdat)
00488 /********************************************************************\
00489 Routine: ybk_close_chaos
00490 Purpose: patch the end of the event to the next 4 byte boundary,
00491 fills up the bank header,
00492 compute the data size in bt unit.
00493 update the LRL (pevt)
00494 Input:
00495 DWORD * pevt          pointer to the top of the YBOS event (LRL).
00496 DWORD   bt            bank type
00497 I2_BKTYPE, I1_BKTYPE, I4_BKTYPE, F4_BKTYPE
00498 void  * pbkdat        pointer to the user area
00499 Output:
00500 none
00501 Function value: Number of bytes in the bank.
00502 \********************************************************************/
00503 {
00504    switch (bktype) {
00505    case D8_BKTYPE:
00506       *__pchaosi4 = (DWORD) ((double *) pbkdat - (double *) __pchaosi4 - 1);
00507       break;
00508    case I4_BKTYPE:
00509    case F4_BKTYPE:
00510       *__pchaosi4 = (DWORD) ((DWORD *) pbkdat - __pchaosi4 - 1);
00511       break;
00512    case I2_BKTYPE:
00513       *__pchaosi4 = (DWORD) ((WORD *) pbkdat - (WORD *) __pchaosi4 - 2);
00514       SWAP_D2WORD(__pchaosi4);
00515       break;
00516    case I1_BKTYPE:
00517    case A1_BKTYPE:
00518       *__pchaosi4 = (DWORD) ((BYTE *) pbkdat - (BYTE *) __pchaosi4 - 4);
00519       break;
00520    default:
00521       printf(" unknown YBOS bank type (%ld)\n", bktype);
00522       break;
00523    }
00524 
00525    return ybk_close(plrl, pbkdat);
00526 }
00527 
00528 /**dox***************************************************************/
00529 #endif                          /* DOXYGEN_SHOULD_SKIP_THIS */
00530 
00531 /********************************************************************/
00532 /**
00533 Close the YBOS bank previously created by ybk_create().
00534 
00535 The data pointer pdata must be obtained by ybk_create() and
00536 used as an address to fill a bank. It is incremented with every value written
00537 to the bank and finally points to a location just after the last byte of the
00538 bank. It is then passed to ybk_close() to finish the bank creation. YBOS is a
00539 4 bytes bank aligned structure. Padding is performed at the closing of the bank
00540 with values of 0x0f or/and 0x0ffb. See @ref YBOS_bank_examples.
00541 @param plrl pointer to current composed event.
00542 @param pbkdat  pointer to the current data.
00543 @return number number of bytes contained in bank.
00544 */
00545 INT ybk_close(DWORD * plrl, void *pbkdat)
00546 {
00547    DWORD tdlen;
00548    /* align pbkdat to I*4 */
00549    if (((DWORD) pbkdat & 0x1) != 0) {
00550       *((BYTE *) pbkdat) = 0x0f;
00551       pbkdat = (void *) (((BYTE *) pbkdat) + 1);
00552    }
00553    if (((DWORD) pbkdat & 0x2) != 0) {
00554       *((WORD *) pbkdat) = 0x0ffb;
00555       pbkdat = (void *) (((WORD *) pbkdat) + 1);
00556    }
00557 
00558    /* length in byte */
00559    tdlen = (DWORD) ((char *) pbkdat - (char *) __pbkh - sizeof(YBOS_BANK_HEADER));
00560 
00561    /* YBOS bank length in I4 */
00562    __pbkh->length = (tdlen + 4) / 4;    /* (+Bank Type &@#$!) YBOS bank length */
00563 
00564    /* adjust Logical Record Length (entry point from the system) */
00565    *plrl += __pbkh->length + (sizeof(YBOS_BANK_HEADER) / 4) - 1;
00566    return __pbkh->length;
00567 }
00568 
00569 /********************************************************************/
00570 /**
00571 Returns the size in bytes of the event composed of YBOS bank(s).
00572 @param plrl pointer to the area of event
00573 @return number of bytes contained in data area of the event 
00574 */
00575 INT ybk_size(DWORD * plrl)
00576 {
00577    return (*((DWORD *) plrl) * 4 + 4);
00578 }
00579 
00580 /********************************************************************/
00581 /**
00582 Returns the size in bytes of the event composed of YBOS bank(s).
00583 
00584 The bk_list() has to be a predefined string of max size of
00585 YB_STRING_BANKLIST_MAX.
00586 @param plrl pointer to the area of event
00587 @param bklist Filled character string of the YBOS bank names found in the event.
00588 @return number of banks found in this event.
00589 */
00590 INT ybk_list(DWORD * plrl, char *bklist)
00591 {
00592 
00593    YBOS_BANK_HEADER *pbk;
00594    DWORD *pendevt, nbk;
00595 
00596    pbk = (YBOS_BANK_HEADER *) (plrl + 1);
00597 
00598    /* end of event pointer skip LRL, point to YBOS_BANK_HEADER */
00599    pendevt = (DWORD *) pbk + *plrl;
00600 
00601    /* check if bank_type in range */
00602    if (pbk->type >= MAX_BKTYPE)
00603       return (YB_WRONG_BANK_TYPE);
00604 
00605    /*init bank counter and returned string */
00606    nbk = 0;
00607    bklist[0] = 0;
00608 
00609    /* scan event */
00610    while ((DWORD *) pbk < pendevt) {
00611       /* update the number of bank counter */
00612       nbk++;
00613 
00614       if (nbk > YB_BANKLIST_MAX) {
00615          cm_msg(MINFO, "ybk_list", "over %i banks -> truncated", YB_BANKLIST_MAX);
00616          return (nbk);
00617       }
00618 
00619       /* append ybos bank name to list */
00620       strncat(bklist, (char *) &(pbk->name), 4);
00621 
00622       /* skip to next bank */
00623       pbk = (YBOS_BANK_HEADER *) (((DWORD *) pbk) + pbk->length + 4);
00624    }
00625    return (nbk);
00626 }
00627 
00628 /********************************************************************/
00629 /**
00630 Find the requested bank and return the infirmation if the bank as well
00631 as the pointer to the top of the data section.
00632 @param plrl     pointer to the area of event.
00633 @param bkname   name of the bank to be located.
00634 @param bklen    returned length in 4bytes unit of the bank.
00635 @param bktype   returned bank type.
00636 @param pbk      pointer to the first data of the found bank.
00637 @return  YB_SUCCESS, YB_BANK_NOT_FOUND, YB_WRONG_BANK_TYPE
00638 */
00639 INT ybk_find(DWORD * plrl, char *bkname, DWORD * bklen, DWORD * bktype, void **pbk)
00640 {
00641    YBOS_BANK_HEADER *pevt;
00642    DWORD *pendevt;
00643 
00644    pevt = (YBOS_BANK_HEADER *) (plrl + 1);
00645 
00646    /* end of event pointer skip LRL, point to YBOS_BANK_HEADER */
00647    pendevt = (DWORD *) pevt + *plrl;
00648 
00649    /* check if bank_type in range */
00650    if (pevt->type >= MAX_BKTYPE)
00651       return (YB_WRONG_BANK_TYPE);
00652 
00653    /* init returned variables */
00654    *bklen = 0;
00655    *bktype = 0;
00656 
00657    /* scan event */
00658    while ((DWORD *) pevt < pendevt) {
00659       /* check bank name */
00660       if (strncmp((char *) &(pevt->name), bkname, 4) == 0) {    /* bank name match */
00661          /* extract bank length */
00662          *bklen = pevt->length - 1;     /* exclude bank type */
00663 
00664          /* extract bank type */
00665          *bktype = pevt->type;
00666 
00667          /* return point to bank name */
00668          *pbk = &pevt->name;
00669          return (YB_SUCCESS);
00670       } else {
00671          /* skip to next bank */
00672          pevt = (YBOS_BANK_HEADER *) (((DWORD *) pevt) + pevt->length + 4);
00673       }
00674    }
00675    return (YB_BANK_NOT_FOUND);
00676 }
00677 
00678 /********************************************************************/
00679 /**
00680 Locate the requested bank and return the pointer to the top of the data section.
00681 @param plrl pointer to the area of event
00682 @param bkname name of the bank to be located.
00683 @param pdata pointer to the first data of the located bank.
00684 @return  Number of DWORD in bank or YB_BANK_NOT_FOUND, YB_WRONG_BANK_TYPE (<0)
00685 */
00686 INT ybk_locate(DWORD * plrl, char *bkname, void *pdata)
00687 {
00688    YBOS_BANK_HEADER *pybk;
00689    DWORD *pendevt;
00690 
00691    pybk = (YBOS_BANK_HEADER *) (plrl + 1);
00692 
00693    /* end of event pointer skip LRL, point to YBOS_BANK_HEADER */
00694    pendevt = (DWORD *) pybk + *plrl;
00695 
00696    /* check if bank_type in range */
00697    if (pybk->type >= MAX_BKTYPE)
00698       return (YB_WRONG_BANK_TYPE);
00699 
00700    /* scan event */
00701    while ((DWORD *) pybk < pendevt) {
00702       /* check bank name */
00703       if (strncmp((char *) &(pybk->name), bkname, 4) == 0) {    /* bank name match */
00704          /* extract bank length */
00705 
00706          /* return pointer to data section */
00707          *((void **) pdata) = pybk + 1;
00708          return (pybk->length - 1);
00709       } else {
00710          /* skip to next bank */
00711          pybk = (YBOS_BANK_HEADER *) (((DWORD *) pybk) + pybk->length + 4);
00712       }
00713    }
00714    return (YB_BANK_NOT_FOUND);
00715 }
00716 
00717 /********************************************************************/
00718 /**
00719 Returns the bank header pointer and data pointer of the given bank name.
00720 @param   plrl pointer to the area of event.
00721 @param   pybkh pointer to the YBOS bank header.
00722 @param   pdata pointer to the first data of the current bank.
00723 @return  data length in 4 bytes unit. return -1 if no more bank found.
00724 */
00725 INT ybk_iterate(DWORD * plrl, YBOS_BANK_HEADER ** pybkh, void **pdata)
00726 {
00727    static int len;
00728    static DWORD *pendevt;
00729    static DWORD *pybk;
00730    /*PAA char bname[5]; */
00731 
00732    /* the event may have several bank
00733       check if we have been already in here */
00734    if (*pybkh == NULL) {
00735       /* first time in (skip lrl) */
00736       *pybkh = (YBOS_BANK_HEADER *) (plrl + 1);
00737 
00738       if ((*pybkh)->type > I1_BKTYPE) {
00739          *pdata = NULL;
00740          *pybkh = (YBOS_BANK_HEADER *) * pdata;
00741          return (YB_WRONG_BANK_TYPE);
00742       }
00743 
00744       /* end of event pointer (+ lrl) */
00745       pendevt = plrl + *plrl;
00746 
00747       /* skip the EVID bank if present */
00748     /*-PAA- keep it in for a little while Dec 17/98
00749     *((DWORD *)bname) = (*pybkh)->name;
00750     if (strncmp (bname,"EVID",4) == 0)
00751     {
00752     len = (*pybkh)->length;
00753     (YBOS_BANK_HEADER *)(*pybkh)++;
00754     pybk = (DWORD *) *pybkh;
00755     pybk += len - 1;
00756     *pybkh = (YBOS_BANK_HEADER *) pybk;
00757     }
00758     */
00759    } else {
00760       /* already been in iterate */
00761       /* skip current pointed bank ( + bank_length + header) */
00762       len = (*pybkh)->length;
00763       (YBOS_BANK_HEADER *) (*pybkh)++;
00764       pybk = (DWORD *) * pybkh;
00765       pybk += len - 1;
00766       *pybkh = (YBOS_BANK_HEADER *) pybk;
00767    }
00768 
00769    /* check for end of event */
00770    if ((DWORD *) (*pybkh) < pendevt) {
00771       /* points to the data section */
00772       *pdata = (void *) (*pybkh + 1);
00773 
00774       /* length always in I*4 due to YBOS -1 because type included in length !@# */
00775       return ((*pybkh)->length - 1);
00776    } else {
00777       /* no more bank in this event */
00778       *pdata = NULL;
00779       *pybkh = (YBOS_BANK_HEADER *) * pdata;
00780       return (-1);
00781    }
00782 }
00783 
00784 /**dox***************************************************************/
00785 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00786 
00787 /*-- GENERAL file fragmentation and recovery -----Section d)--------*/
00788 /*-- GENERAL file fragmentation and recovery -----------------------*/
00789 /*-- GENERAL file fragmentation and recovery -----------------------*/
00790 /*-- GENERAL file fragmentation and recovery -----------------------*/
00791 /*------------------------------------------------------------------*/
00792 INT feodb_file_dump(EQUIPMENT * eqp, char *eqpname,
00793                     char *pevent, INT run_number, char *path)
00794 /********************************************************************\
00795 Routine: feodb_file_dump
00796 Purpose: Access ODB for the /Equipment/<equip_name>/Dump.
00797 in order to scan for file name and dump the files content to the
00798 Midas buffer channel.
00799 Input:
00800 EQUIPMENT * eqp           Current equipment
00801 INT       run_number      current run_number
00802 char      * path          full file name specification
00803 Output:
00804 none
00805 Function value:
00806 0                      Successful completion
00807 DB_INVALID_NAME        Equipment doesn't match request
00808 \********************************************************************/
00809 {
00810    EQUIPMENT *peqp;
00811    INT index, size, status;
00812    HNDLE hDB, hKey, hKeydump;
00813    char strpath[MAX_FILE_PATH], Dumpfile[MAX_FILE_PATH];
00814    char odb_entry[MAX_FILE_PATH];
00815    BOOL eqpfound = FALSE;
00816 
00817    cm_get_experiment_database(&hDB, &hKey);
00818    peqp = eqp;
00819 
00820    /* find the equipment info for this job */
00821    while (*(peqp->name) != 0) {
00822       if (equal_ustring((peqp->name), eqpname)) {
00823          eqpfound = TRUE;
00824          break;
00825       }
00826       peqp++;
00827    }
00828    if (!eqpfound)
00829       return DB_INVALID_NAME;
00830 
00831    /* loop over all channels */
00832    sprintf(odb_entry, "/Equipment/%s/Dump", path);
00833    status = db_find_key(hDB, 0, odb_entry, &hKey);
00834    if (status != DB_SUCCESS) {
00835       cm_msg(MINFO, "ybos_odb_file_dump", "odb_access_file -I- %s not found", odb_entry);
00836       return YB_SUCCESS;
00837    }
00838    index = 0;
00839    while ((status = db_enum_key(hDB, hKey, index, &hKeydump)) != DB_NO_MORE_SUBKEYS) {
00840       if (status == DB_SUCCESS) {
00841          size = sizeof(strpath);
00842          db_get_path(hDB, hKeydump, strpath, size);
00843          db_get_value(hDB, 0, strpath, Dumpfile, &size, TID_STRING, TRUE);
00844          yb_file_fragment(peqp, (EVENT_HEADER *) pevent, run_number, Dumpfile);
00845       }
00846       index++;
00847    }
00848    return (YB_SUCCESS);
00849 }
00850 
00851 /*------------------------------------------------------------------*/
00852 INT yb_file_fragment(EQUIPMENT * eqp, EVENT_HEADER * pevent, INT run_number, char *path)
00853 /********************************************************************\
00854 Routine: yb_file_fragment
00855 Purpose: Fragment file in order to send it through Midas.
00856 Compose an event of the form of:
00857 Midas_header[(YM_CFILE)(YM_PFILE)(YM_DFILE)]
00858 Specific for the fe for either format YBOS/MIDAS
00859 Input:
00860 EQUIPMENT * eqp        Current equipment
00861 INT   run_number       currrent run_number
00862 char * path            full file name specification
00863 Output:
00864 none
00865 Function value:
00866 YB_SUCCESS          Successful completion
00867 SS_FILE_ERROR       file access error
00868 \********************************************************************/
00869 {
00870    INT dmpf, remaining;
00871    INT nread, filesize, nfrag;
00872    INT allheader_size;
00873    DWORD *pbuf, *pcfile, *pmy;
00874    YM_CFILE myc_fileh;
00875    YM_PFILE myp_fileh;
00876    int send_sock, flag;
00877 
00878    /* check if file exists */
00879    /* Open for read (will fail if file does not exist) */
00880    if ((dmpf = open(path, O_RDONLY | O_BINARY | O_LARGEFILE, 0644)) == -1) {
00881       cm_msg(MINFO, "ybos_file_fragment", "File dump -Failure- on open file %s", path);
00882       return SS_FILE_ERROR;
00883    }
00884 
00885    /* get file size */
00886    filestat = (struct stat *) malloc(sizeof(struct stat));
00887    stat(path, filestat);
00888    filesize = filestat->st_size;
00889    free(filestat);
00890    cm_msg(MINFO, "ybos_file_fragment", "Accessing File %s (%i)", path, filesize);
00891 
00892   /*-PAA-Oct06/97 added for ring buffer option */
00893    send_sock = rpc_get_send_sock();
00894 
00895    /* compute fragmentation & initialize */
00896    nfrag = filesize / MAX_FRAG_SIZE;
00897 
00898    /* Generate a unique FILE ID */
00899    srand((unsigned) time(NULL));
00900    srand((unsigned) time(NULL));
00901 
00902    /* Fill file YM_CFILE header */
00903    myc_fileh.file_ID = rand();
00904    myc_fileh.size = filesize;
00905    myc_fileh.total_fragment = nfrag + (((filesize % MAX_FRAG_SIZE) == 0) ? 0 : 1);
00906    myc_fileh.current_fragment = 0;
00907    myc_fileh.current_read_byte = 0;
00908    myc_fileh.run_number = run_number;
00909    myc_fileh.spare = 0x1234abcd;
00910 
00911    /* Fill file YM_PFILE header */
00912    memset(myp_fileh.path, 0, sizeof(YM_PFILE));
00913    /* first remove path if present */
00914    if (strrchr(path, '/') != NULL) {
00915       strncpy(myp_fileh.path, strrchr(path, '/') + 1, strlen(strrchr(path, '/')));
00916    } else
00917       strcpy(myp_fileh.path, path);
00918 
00919    /* allocate space */
00920    allheader_size = sizeof(EVENT_HEADER)
00921        + sizeof(YBOS_BANK_HEADER)       /* EVID bank header */
00922        +5 * sizeof(DWORD)       /* EVID data size */
00923        +sizeof(YM_CFILE)
00924        + sizeof(YM_PFILE) + 64;
00925 
00926    flag = 0;
00927    pevent -= 1;
00928 
00929    /* read file */
00930    while (myc_fileh.current_fragment <= nfrag) {
00931       /* pevent passed by fe for first event only */
00932       if (flag)
00933          pevent = dm_pointer_get();
00934       flag = 1;
00935 
00936       /* bank header */
00937       pmy = (DWORD *) (pevent + 1);
00938 
00939     /*-PAA-Oct06/97 for ring buffer reset the LRL */
00940       if (eqp->format == FORMAT_YBOS)
00941          ybk_init((DWORD *) pmy);
00942       else if (eqp->format == FORMAT_MIDAS)
00943          bk_init(pmy);
00944 
00945     /*---- EVID bank ----*/
00946       if (eqp->format == FORMAT_YBOS) {
00947          YBOS_EVID_BANK(pmy, myc_fileh.current_fragment,
00948                         (eqp->info.event_id << 16) | (eqp->info.trigger_mask)
00949                         , eqp->serial_number, run_number);
00950       } else if (eqp->format == FORMAT_MIDAS) {
00951          MIDAS_EVID_BANK(pmy, myc_fileh.current_fragment,
00952                          (eqp->info.event_id << 16) | (eqp->info.trigger_mask)
00953                          , eqp->serial_number, run_number);
00954       }
00955 
00956       /* Create Control file bank */
00957       if (eqp->format == FORMAT_YBOS)
00958          ybk_create(pmy, "CFIL", I4_BKTYPE, (DWORD *) & pbuf);
00959       else if (eqp->format == FORMAT_MIDAS)
00960          bk_create(pmy, "CFIL", TID_DWORD, &pbuf);
00961 
00962       /* save pointer for later */
00963       pcfile = pbuf;
00964       pbuf = (DWORD *) (((char *) pbuf) + sizeof(YM_CFILE));
00965       if (eqp->format == FORMAT_YBOS)
00966          ybk_close(pmy, pbuf);
00967       else if (eqp->format == FORMAT_MIDAS)
00968          bk_close(pmy, pbuf);
00969 
00970       /* Create Path file name bank */
00971       if (eqp->format == FORMAT_YBOS)
00972          ybk_create(pmy, "PFIL", A1_BKTYPE, (DWORD *) & pbuf);
00973       else if (eqp->format == FORMAT_MIDAS)
00974          bk_create(pmy, "PFIL", TID_CHAR, &pbuf);
00975       memcpy((char *) pbuf, (char *) &myp_fileh, sizeof(YM_PFILE));
00976       pbuf = (DWORD *) (((char *) pbuf) + sizeof(YM_CFILE));
00977       if (eqp->format == FORMAT_YBOS)
00978          ybk_close(pmy, pbuf);
00979       else if (eqp->format == FORMAT_MIDAS)
00980          bk_close(pmy, pbuf);
00981 
00982       /* file content */
00983       if (eqp->format == FORMAT_YBOS)
00984          ybk_create(pmy, "DFIL", A1_BKTYPE, (DWORD *) & pbuf);
00985       else if (eqp->format == FORMAT_MIDAS)
00986          bk_create(pmy, "DFIL", TID_CHAR, (DWORD *) & pbuf);
00987       /* compute data length */
00988       remaining = filesize - myc_fileh.current_read_byte;
00989       nread =
00990           read(dmpf, (char *) pbuf,
00991                (remaining > MAX_FRAG_SIZE) ? MAX_FRAG_SIZE : remaining);
00992       /* adjust target pointer */
00993       pbuf = (DWORD *) (((char *) pbuf) + nread);
00994       /* keep track of statistic */
00995       myc_fileh.current_fragment++;
00996       myc_fileh.fragment_size = nread;
00997       myc_fileh.current_read_byte += nread;
00998       memcpy((char *) pcfile, (char *) &myc_fileh, sizeof(YM_CFILE));
00999 
01000       /* close YBOS bank */
01001       if (eqp->format == FORMAT_YBOS)
01002          ybk_close(pmy, pbuf);
01003       else if (eqp->format == FORMAT_MIDAS)
01004          bk_close(pmy, pbuf);
01005 
01006       /* Fill the Midas header */
01007       if (eqp->format == FORMAT_YBOS)
01008          bm_compose_event(pevent, eqp->info.event_id,
01009                           eqp->info.trigger_mask, ybk_size(pmy), eqp->serial_number++);
01010       else if (eqp->format == FORMAT_MIDAS)
01011          bm_compose_event(pevent, eqp->info.event_id,
01012                           eqp->info.trigger_mask, bk_size(pmy), eqp->serial_number++);
01013 
01014     /*-PAA-Oct06/97 Added the ring buffer option for FE event send */
01015       eqp->bytes_sent += pevent->data_size + sizeof(EVENT_HEADER);
01016       eqp->events_sent++;
01017       if (eqp->buffer_handle) {
01018     /*-PAA- Jun98 These events should be sent directly as they come before the run
01019     started. If the event channel has to be used, then care should be taken
01020     if interrupt are being used too. May requires buffer checks like in
01021       scheduler (mfe.c) */
01022          /* #undef USE_EVENT_CHANNEL */
01023 #ifdef USE_EVENT_CHANNEL
01024          dm_pointer_increment(eqp->buffer_handle,
01025                               pevent->data_size + sizeof(EVENT_HEADER));
01026 #else
01027          rpc_flush_event();
01028          bm_send_event(eqp->buffer_handle, pevent,
01029                        pevent->data_size + sizeof(EVENT_HEADER), SYNC);
01030 #endif
01031          eqp->odb_out++;
01032       }
01033    }
01034    /* close file */
01035    if (close(dmpf)) {
01036       cm_msg(MERROR, "fe_file_dump", "cannot close file: %s", path);
01037       return SS_FILE_ERROR;
01038    }
01039    return YB_SUCCESS;
01040 }
01041 
01042 /* Used in mfe */
01043 INT ybos_get_tid_size(INT tid)
01044 {
01045    if (tid < 8)
01046       return yb_tid_size[tid];
01047    return 0;
01048 }
01049 
01050 /*
01051 The entrie section below will not be included in the VxWorks built of the
01052 libmidas.a library. All the functions are logger, mdump related and therefore
01053 certaintly of no use under this OS. 
01054 */
01055 #if !defined (OS_VXWORKS)       /* Frontend */
01056 /*---- LOGGER YBOS format routines ----Section b)--------------------------*/
01057 /*---- LOGGER YBOS format routines ----------------------------------------*/
01058 /*---- LOGGER YBOS format routines ----------------------------------------*/
01059 /*---- LOGGER YBOS format routines ----------------------------------------*/
01060 /*---- LOGGER YBOS format routines ----------------------------------------*/
01061 
01062 INT ybos_log_open(LOG_CHN * log_chn, INT run_number)
01063 /********************************************************************\
01064 Routine: ybos_log_open, Should be used only by mlogger.
01065 Purpose: Open a logger channel in YBOS fmt
01066 Input:
01067 LOG_CHN * log_chn      Concern log channel
01068 INT   run_number       run number
01069 Output:
01070 none
01071 Function value:
01072 error, success
01073 \********************************************************************/
01074 {
01075    YBOS_INFO *ybos;
01076    INT status;
01077 
01078    /* allocate YBOS buffer info */
01079    log_chn->format_info = (void **) malloc(sizeof(YBOS_INFO));
01080 
01081    ybos = (YBOS_INFO *) log_chn->format_info;
01082 
01083    /* reset memory */
01084    memset(ybos, 0, sizeof(YBOS_INFO));
01085 
01086    if (ybos == NULL) {
01087       log_chn->handle = 0;
01088       return SS_NO_MEMORY;
01089    }
01090 
01091    /* allocate full ring buffer for that channel */
01092    if ((ybos->ptop = (DWORD *) malloc(YBOS_BUFFER_SIZE)) == NULL) {
01093       log_chn->handle = 0;
01094       return SS_NO_MEMORY;
01095    }
01096 
01097    memset((char *) ybos->ptop, 0, YBOS_BUFFER_SIZE);
01098    /* Setup YBOS pointers */
01099    ybos->reco = YBOS_HEADER_LENGTH;
01100    ybos->pbuf = ybos->ptop + YBOS_HEADER_LENGTH;
01101    ybos->pwrt = ybos->pbuf;
01102    ybos->pbot = ybos->ptop + YBOS_PHYREC_SIZE;
01103    ybos->pend = ybos->ptop + YBOS_BUFFER_SIZE;
01104    ybos->recn = 0;
01105    /* open logging device */
01106    status = ybos_logfile_open(log_chn->type, log_chn->path, &log_chn->handle);
01107    if (status != SS_SUCCESS) {
01108       free(ybos->ptop);
01109       free(ybos);
01110       log_chn->handle = 0;
01111       return status;
01112    }
01113 
01114    /* write ODB dump */
01115    if (log_chn->settings.odb_dump)
01116       ybos_log_dump(log_chn, EVENTID_BOR, run_number);
01117 
01118    return SS_SUCCESS;
01119 }
01120 
01121 /*------------------------------------------------------------------*/
01122 INT ybos_logfile_open(INT type, char *path, HNDLE * handle)
01123 /********************************************************************\
01124 Routine: ybos_logfile_open
01125 Purpose: Open a YBOS logging channel for either type (Disk/Tape)
01126 The device open is taken care here. But the writting is done
01127 through yb_any_dev_os_write for ybos magta.
01128 
01129 Input:
01130 INT type       : Disk, Tape
01131 char * path    : Device name
01132 
01133 Output:
01134 HNDLE * handle ; returned handle of the open device
01135 none
01136 Function value:
01137 error, success
01138 \********************************************************************/
01139 {
01140 #ifdef YBOS_VERSION_3_3
01141    INT status;
01142    DWORD written;
01143 #endif
01144 
01145    /* Create device channel */
01146    if (type == LOG_TYPE_TAPE) {
01147     /*-PAA- Should check for the TAPE_BUFFER_SIZE set in ss_tape_open() */
01148       return ss_tape_open(path, O_WRONLY | O_CREAT | O_TRUNC, handle);
01149    } else if (type == LOG_TYPE_DISK) {
01150 #ifdef OS_WINNT
01151       *handle =
01152           (int) CreateFile(path, GENERIC_WRITE, FILE_SHARE_READ, NULL,
01153                            CREATE_ALWAYS,
01154                            FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH
01155                            | FILE_FLAG_SEQUENTIAL_SCAN, 0);
01156 #else
01157       *handle = open(path, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE, 0644);
01158 #endif
01159       if (*handle < 0)
01160          return SS_FILE_ERROR;
01161 #ifdef YBOS_VERSION_3_3
01162       /* specific to YBOS Disk structure */
01163       /* write MAGTA header in bytes 0x4, "*BOT" */
01164       status = yb_any_dev_os_write(*handle, type, (char *) magta, 8, &written);
01165       if (status != SS_SUCCESS)
01166          return status;
01167 
01168       /* allocate temporary emtpy record */
01169       pbot = realloc(pbot, magta[2] - 4);
01170       memset((char *) pbot, 0, magta[2] - 4);
01171       /* write BOT empty record for MAGTA */
01172       status = yb_any_dev_os_write(*handle, type, (char *) pbot, magta[2] - 4, &written);
01173       if (status != SS_SUCCESS)
01174          return status;
01175 #endif
01176    }
01177    return YB_SUCCESS;
01178 }
01179 
01180 /*------------------------------------------------------------------*/
01181 INT ybos_write(LOG_CHN * log_chn, EVENT_HEADER * pevent, INT evt_size)
01182 /********************************************************************\
01183 Routine: ybos_write
01184 Purpose: Write a YBOS event to the logger channel. Should be used only by 
01185 mlogger.
01186 Takes care of the EVENT_BOR and EVENT_MESSAGE which are 
01187 shiped as YBOS bank in A1_BKTYPE bank. named respectively
01188 MODB, MMSG
01189 Input:
01190 LOG_CHN *      log_chn      Concern log channel
01191 EVENT_HEADER * pevent       event pointer to Midas header
01192 INT            evt_size     event size in bytes seen by Midas
01193 Output:
01194 none
01195 Function value:
01196 error, success
01197 \********************************************************************/
01198 {
01199    short int evid, evmsk;
01200    BOOL large_evt;
01201    INT status, left_over_length, datasize;
01202    YBOS_INFO *ybos;
01203    DWORD *pbkdat;
01204    DWORD bfsize;
01205    YBOS_PHYSREC_HEADER *yb_phrh;
01206 
01207    /* Check the Event ID for :
01208       Midas BOR/EOR which include the ODB dump : 0x8000/0x8001
01209       Msg dump from MUSER flag from odb mainly : 0x8002
01210     */
01211 
01212    evid = pevent->event_id;
01213    evmsk = pevent->trigger_mask;
01214 
01215    /* shortcut to ybos struct */
01216    ybos = (YBOS_INFO *) log_chn->format_info;
01217 
01218    /* detect if event is message oriented (ASCII) */
01219    if ((evid >= EVENTID_BOR) && (evid <= EVENTID_MESSAGE)) {    /* skip ASCII dump if not MUSER */
01220       if (!(evmsk & MT_USER))
01221          return SS_SUCCESS;
01222 
01223       /* skip if MUSER  but not Log message enabled */
01224       if (MT_USER && !log_chn->settings.log_messages)
01225          return SS_SUCCESS;
01226 
01227       /* ASCII event has to be recasted YBOS */
01228       /* Inform if event too long (>32Kbytes) */
01229       if (pevent->data_size > MAX_EVENT_SIZE)
01230          cm_msg(MINFO, "ybos_write", "MMSG or MODB event too large");
01231 
01232       /* align to DWORD boundary in bytes */
01233       datasize = 4 * (pevent->data_size + 3) / 4;
01234 
01235       /* overall buffer size in bytes */
01236       bfsize = datasize + sizeof(YBOS_BANK_HEADER) + 4; /* +LRL */
01237 
01238       /* allocate space */
01239       pbktop = (DWORD *) malloc(bfsize);
01240       if (pbktop == NULL) {
01241          cm_msg(MERROR, "ybos_write", "malloc error for ASCII dump");
01242          return SS_NO_MEMORY;
01243       }
01244       memset(pbktop, 0, bfsize);
01245       ybk_init(pbktop);
01246 
01247       /* open bank depending on event type */
01248       if (evid == EVENTID_MESSAGE)
01249          ybk_create(pbktop, "MMSG", A1_BKTYPE, &pbkdat);
01250       else
01251          ybk_create(pbktop, "MODB", A1_BKTYPE, &pbkdat);
01252 
01253       memcpy((char *) pbkdat, (char *) (pevent + 1), pevent->data_size);
01254       pbkdat = (DWORD *) (((char *) pbkdat) + datasize);
01255       ybk_close(pbktop, pbkdat);
01256 
01257       /* event size in bytes for Midas */
01258       evt_size = ybk_size(pbktop);
01259 
01260       /* swap bytes if necessary based on the ybos.bank_type */
01261       ybos_event_swap((DWORD *) pbktop);
01262 
01263       /* Event with MIDAS header striped out */
01264       memcpy((char *) ybos->pbuf, (char *) pbktop, evt_size);
01265 
01266       if (pbktop != NULL)
01267          free(pbktop);
01268       pbktop = NULL;
01269       status = SS_SUCCESS;
01270    } else {                     /* normal event */
01271       /* Strip the event from the Midas EVENT_HEADER */
01272       /* event size include the Midas EVENT_HEADER... don't need for ybos
01273          I do this in order to keep the log_write from mlogger intact */
01274 
01275       /* correct the event length. Now it is a pure YBOS event */
01276       pevent++;
01277 
01278       /* correct the event length in bytes */
01279       evt_size -= sizeof(EVENT_HEADER);
01280 
01281       /* swap bytes if necessary based on the ybos.bank_type */
01282       ybos_event_swap((DWORD *) pevent);
01283 
01284       /* I have ALWAYS enough space for the event <MAX_EVENT_SIZE */
01285       memcpy((char *) ybos->pbuf, (char *) pevent, evt_size);
01286 
01287       status = YB_SUCCESS;
01288    }
01289 
01290    /* move write pointer to next free location (DWORD) */
01291    ybos->pbuf += (4 * (evt_size + 3) / 4) >> 2;
01292 
01293    /* default not a large event */
01294    large_evt = FALSE;
01295 
01296    /* Loop over buffer until this condition 
01297       The event offset in the phys rec is ==0 if event larger than PHYREC_SIZE */
01298    while (ybos->pbuf >= ybos->pbot) {
01299       ybos->pwrt -= YBOS_HEADER_LENGTH;
01300       yb_phrh = (YBOS_PHYSREC_HEADER *) (ybos->pwrt);
01301       yb_phrh->rec_size = YBOS_PHYREC_SIZE - 1; /* exclusive */
01302       yb_phrh->header_length = YBOS_HEADER_LENGTH;
01303       yb_phrh->rec_num = ybos->recn;
01304       yb_phrh->offset = large_evt ? 0 : ybos->reco;
01305 
01306       /* Write physical record to device */
01307       status =
01308           yb_any_log_write(log_chn->handle, log_chn->format, log_chn->type,
01309                            ybos->pwrt, YBOS_PHYREC_SIZE << 2);
01310       if (status != SS_SUCCESS)
01311          return status;
01312 
01313       /* update statistics */
01314 #ifdef YBOS_VERSION_3_3
01315       if (log_chn->type == LOG_TYPE_TAPE) {     /* statistics in bytes */
01316          log_chn->statistics.bytes_written += YBOS_PHYREC_SIZE << 2;
01317          log_chn->statistics.bytes_written_total += YBOS_PHYREC_SIZE << 2;
01318       } else {                  /* statistics in bytes + the extra magta */
01319          log_chn->statistics.bytes_written += YBOS_PHYREC_SIZE << 2 + 4;
01320          log_chn->statistics.bytes_written_total += YBOS_PHYREC_SIZE << 2 + 4;
01321       }
01322 #else
01323       log_chn->statistics.bytes_written += YBOS_PHYREC_SIZE << 2;
01324       log_chn->statistics.bytes_written_total += YBOS_PHYREC_SIZE << 2;
01325 #endif
01326 
01327       /* Update statistics */
01328       ybos->recn++;
01329 
01330       /* check if event is larger than YBOS_PHYREC_SIZE */
01331       if (ybos->pbuf >= ybos->pbot + (YBOS_PHYREC_SIZE - YBOS_HEADER_LENGTH)) {
01332          large_evt = TRUE;
01333          /* shift record window by one YBOS_PHYSREC - header */
01334          ybos->pwrt = ybos->pbot;
01335          ybos->pbot += (YBOS_PHYREC_SIZE - YBOS_HEADER_LENGTH);
01336       } else {
01337          large_evt = FALSE;
01338          /* adjust pointers */
01339          ybos->pwrt = ybos->ptop + YBOS_HEADER_LENGTH;
01340          left_over_length = ybos->pbuf - ybos->pbot;
01341          memcpy(ybos->pwrt, ybos->pbot, left_over_length << 2); /* in bytes */
01342          ybos->pbuf = ybos->pwrt + left_over_length;
01343          ybos->pbot = ybos->ptop + YBOS_PHYREC_SIZE;
01344          ybos->reco = ybos->pbuf - ybos->pwrt + 4;      /* YBOS header */
01345       }
01346    }
01347 
01348    /* update statistics */
01349    log_chn->statistics.events_written++;
01350 
01351    return status;
01352 }
01353 
01354 /*------------------------------------------------------------------*/
01355 INT ybos_buffer_flush(LOG_CHN * log_chn, INT run_number)
01356 /********************************************************************\
01357 Routine: ybos_buffer_flush
01358 Purpose: Empty the internal buffer to logger channel for YBOS fmt
01359 YBOS end of run marks (End of file) is -1 in the *plrl
01360 I'm writting an extra FULL YBOS_PHYSREC_SIZE of -1
01361 Input:
01362 LOG_CHN * log_chn      Concern log channel
01363 Output:
01364 none
01365 Function value:
01366 error, success
01367 \********************************************************************/
01368 {
01369    INT status;
01370    YBOS_INFO *ybos;
01371    YBOS_PHYSREC_HEADER *yb_phrh;
01372 
01373    ybos = (YBOS_INFO *) log_chn->format_info;
01374 
01375    /* dump the ODB if necessary */
01376    if (log_chn->settings.odb_dump)
01377       ybos_log_dump(log_chn, EVENTID_EOR, run_number);
01378 
01379    /* adjust read pointer to beg of record */
01380    ybos->pwrt -= YBOS_HEADER_LENGTH;
01381    yb_phrh = (YBOS_PHYSREC_HEADER *) ybos->pwrt;
01382 
01383    yb_phrh->rec_size = YBOS_PHYREC_SIZE - 1;    /* exclusive */
01384    yb_phrh->header_length = YBOS_HEADER_LENGTH; /* inclusive */
01385    yb_phrh->rec_num = ybos->recn;
01386    yb_phrh->offset = ybos->reco;        /* exclusive from block_size */
01387 
01388 /* YBOS known only about fix record size. The way to find out
01389 it there is no more valid event is to look at the LRL for -1
01390   put some extra -1 in the current physical record */
01391    memset((DWORD *) ybos->pbuf, -1, YBOS_PHYREC_SIZE << 2);
01392 
01393    /* write record to device */
01394    status =
01395        yb_any_log_write(log_chn->handle, log_chn->format, log_chn->type,
01396                         ybos->pwrt, YBOS_PHYREC_SIZE << 2);
01397 #ifdef YBOS_VERSION_3_3
01398    if (log_chn->type == LOG_TYPE_TAPE) {
01399       log_chn->statistics.bytes_written += YBOS_PHYREC_SIZE << 2;
01400       log_chn->statistics.bytes_written_total += YBOS_PHYREC_SIZE << 2;
01401    } else {
01402       /* write MAGTA header (4bytes)=0x7ff8 */
01403       log_chn->statistics.bytes_written += YBOS_PHYREC_SIZE << 2 + 4;
01404       log_chn->statistics.bytes_written_total += YBOS_PHYREC_SIZE << 2 + 4;
01405    }
01406 #else
01407    log_chn->statistics.bytes_written += YBOS_PHYREC_SIZE << 2;
01408    log_chn->statistics.bytes_written_total += YBOS_PHYREC_SIZE << 2;
01409 #endif
01410    return status;
01411 }
01412 
01413 /*------------------------------------------------------------------*/
01414 INT ybos_logfile_close(INT type, HNDLE handle)
01415 /********************************************************************\
01416 Routine: ybos_logfile_close
01417 Purpose: close a logging channel for either type (Disk/Tape)
01418 For the tape I'm writting just a EOF and expect the rewind command to 
01419 write another one if necessary. This way the run restart is faster.
01420 Input:
01421 INT type       : Disk, Tape
01422 HNDLE * handle ; returned handle of the open device
01423 
01424 Output:
01425 none
01426 Function value:
01427 error, success
01428 \********************************************************************/
01429 {
01430    INT status;
01431    /* Write EOF if Tape */
01432    if (type == LOG_TYPE_TAPE) {
01433       /* writing EOF mark on tape only */
01434       status = ss_tape_write_eof(handle);
01435 #ifdef OS_UNIX
01436       if (status != SS_SUCCESS) {
01437          if (errno == EIO)
01438             return SS_IO_ERROR;
01439          if (errno == ENOSPC)
01440             return SS_NO_SPACE;
01441          else
01442             return status;
01443       }
01444 #endif
01445 #ifdef OS_WINNT
01446       if (status != SS_SUCCESS) {
01447          if (errno == ERROR_END_OF_MEDIA)
01448             return SS_NO_SPACE;
01449          else
01450             return status;
01451       }
01452 #endif
01453 
01454       ss_tape_close(handle);
01455    } else if (type == LOG_TYPE_DISK) {
01456 #ifdef OS_WINNT
01457       CloseHandle((HANDLE) handle);
01458 #else
01459       close(handle);
01460 #endif
01461    }
01462    return YB_SUCCESS;
01463 }
01464 
01465 
01466 /*------------------------------------------------------------------*/
01467 INT ybos_log_close(LOG_CHN * log_chn, INT run_number)
01468 /********************************************************************\
01469 Routine: ybos_log_close
01470 Purpose: Close a YBOS logger channel, Should be used only by mlogger.
01471 Input:
01472 LOG_CHN * log_chn      Concern log channel
01473 INT   run_number       run number
01474 Output:
01475 none
01476 Function value:
01477 error, success
01478 \********************************************************************/
01479 {
01480    INT status;
01481    YBOS_INFO *ybos;
01482 
01483    ybos = (YBOS_INFO *) log_chn->format_info;
01484 
01485    /* Write EOF mark and close the device */
01486    /* flush buffer before closing */
01487    status = ybos_buffer_flush(log_chn, run_number);
01488 
01489    if (status != SS_SUCCESS)
01490       return status;
01491 
01492    status = ybos_logfile_close(log_chn->type, log_chn->handle);
01493 
01494    free(ybos->ptop);
01495    free(ybos);
01496 
01497    return SS_SUCCESS;
01498 }
01499 
01500 /*---- ODB   manipulation   ----------------------------------------*/
01501 void ybos_log_dump(LOG_CHN * log_chn, short int event_id, INT run_number)
01502 /********************************************************************\
01503 Routine: ybos_log_dump, used by mlogger, ybos_log_open
01504 Purpose: Serves the logger flag /logger/settings/ODB dump
01505 Extract the ODB in ASCII format and send it to the logger channel
01506 Compose a ybos bank in A1_BKTYPE regardless of the odb size.
01507 It uses ybos_write to compose the actual event. From here it looks
01508 like a MIDAS event.
01509 Input:
01510 LOG_CHN * log_chn      Concern log channel
01511 short in  event_id     event ID
01512 INT   run_number       run number
01513 Output:
01514 none
01515 Function value:
01516 none
01517 \********************************************************************/
01518 {
01519    INT status, buffer_size, size;
01520    EVENT_HEADER *pevent;
01521    HNDLE hDB;
01522 
01523    cm_get_experiment_database(&hDB, NULL);
01524    /* write ODB dump */
01525    buffer_size = 10000;
01526    do {
01527       pevent = (EVENT_HEADER *) malloc(buffer_size);
01528       if (pevent == NULL) {
01529          cm_msg(MERROR, "ybos_odb_log_dump", "Cannot allocate ODB dump buffer");
01530          break;
01531       }
01532 
01533       size = buffer_size - sizeof(EVENT_HEADER);
01534       status = db_copy(hDB, 0, (char *) (pevent + 1), &size, "");
01535       if (status != DB_TRUNCATED) {
01536          bm_compose_event(pevent, event_id, MIDAS_MAGIC,
01537                           buffer_size - sizeof(EVENT_HEADER) - size + 1, run_number);
01538          ybos_write(log_chn, pevent, pevent->data_size + sizeof(EVENT_HEADER));
01539          break;
01540       }
01541 
01542       /* increase buffer size if truncated */
01543       free(pevent);
01544       buffer_size *= 2;
01545    } while (1);
01546    free(pevent);
01547 }
01548 
01549 /*-- GENERAL mdump functions for MIDAS / YBOS -----Section c)-------*/
01550 /*-- GENERAL mdump functions for MIDAS / YBOS ----------------------*/
01551 /*-- GENERAL mdump functions for MIDAS / YBOS ----------------------*/
01552 /*-- GENERAL mdump functions for MIDAS / YBOS ----------------------*/
01553 /*-- GENERAL mdump functions for MIDAS / YBOS ----------------------*/
01554 /*------------------------------------------------------------------*/
01555 INT yb_any_file_ropen(char *infile, INT data_fmt)
01556 /********************************************************************\
01557 Routine: external yb_any_file_ropen
01558 Purpose: Open data file for replay for the given data format.
01559 It uses the local "my" structure.
01560 Input:
01561 INT data_fmt :  YBOS or MIDAS 
01562 char * infile : Data file name
01563 Output:
01564 none
01565 Function value:
01566 status : from lower function
01567 \********************************************************************/
01568 {
01569    INT status;
01570 
01571    /* fill up record with file name */
01572    strcpy(my.name, infile);
01573 
01574    /* find out what dev it is ? : check on /dev */
01575    my.zipfile = FALSE;
01576    if ((strncmp(my.name, "/dev", 4) == 0) || (strncmp(my.name, "\\\\.\\", 4) == 0)) {
01577       /* tape device */
01578       my.type = LOG_TYPE_TAPE;
01579    } else {
01580       /* disk device */
01581       my.type = LOG_TYPE_DISK;
01582       if (strncmp(infile + strlen(infile) - 3, ".gz", 3) == 0)
01583          my.zipfile = TRUE;
01584    }
01585 
01586    /* open file */
01587    if (!my.zipfile) {
01588       if (my.type == LOG_TYPE_TAPE) {
01589          status = ss_tape_open(my.name, O_RDONLY | O_BINARY, &my.handle);
01590       }
01591       else if ((my.handle = open(my.name, O_RDONLY | O_BINARY | O_LARGEFILE, 0644)) == -1)
01592       {
01593          printf("dev name :%s Handle:%d \n", my.name, my.handle);
01594          return (SS_FILE_ERROR);
01595       }
01596    } else {
01597 #ifdef INCLUDE_ZLIB
01598       if (my.type == LOG_TYPE_TAPE) {
01599          printf(" Zip on tape not yet supported \n");
01600          return (SS_FILE_ERROR);
01601       }
01602       filegz = gzopen(my.name, "rb");
01603       my.handle = 0;
01604       if (filegz == NULL) {
01605          printf("dev name :%s gzopen error:%d \n", my.name, my.handle);
01606          return (SS_FILE_ERROR);
01607       }
01608 #else
01609       cm_msg(MERROR, "ybos.c", "Zlib not included ... gz file not supported");
01610       return (SS_FILE_ERROR);
01611 #endif
01612    }
01613 
01614    if (data_fmt == FORMAT_YBOS) {
01615       my.fmt = FORMAT_YBOS;
01616       my.size = YBOS_PHYREC_SIZE;       /* in DWORD  */
01617       my.pmagta = (char *) malloc(32);
01618       if (my.pmagta == NULL)
01619          return SS_NO_MEMORY;
01620       my.pyh = (YBOS_PHYSREC_HEADER *) malloc(my.size * 14);
01621       if (my.pyh == NULL)
01622          return SS_NO_MEMORY;
01623       (my.pyh)->rec_size = my.size - 1;
01624       (my.pyh)->header_length = YBOS_HEADER_LENGTH;
01625       (my.pyh)->rec_num = 0;
01626       (my.pyh)->offset = 0;
01627       /* current ptr in the physical record */
01628       my.pyrd = (DWORD *) ((DWORD *) my.pyh + (my.pyh)->offset);
01629 
01630       /* allocate memory for one full event */
01631       my.pylrl = (DWORD *) malloc(MAX_EVENT_SIZE);      /* in bytes */
01632       if (my.pylrl == NULL)
01633          return SS_NO_MEMORY;
01634       memset((char *) my.pylrl, -1, MAX_EVENT_SIZE);
01635 
01636       /* reset first path */
01637       my.magtafl = FALSE;
01638    } else if (data_fmt == FORMAT_MIDAS) {
01639       my.fmt = FORMAT_MIDAS;
01640       my.size = TAPE_BUFFER_SIZE;
01641       my.pmp = (char *) malloc(my.size);
01642       if (my.pmp == NULL)
01643          return SS_NO_MEMORY;
01644       my.pme = (EVENT_HEADER *) my.pmp;
01645 
01646       /* allocate memory for one full event */
01647       if (my.pmrd != NULL)
01648          free(my.pmrd);
01649       my.pmrd = (char *) malloc(5 * MAX_EVENT_SIZE);    /* in bytes */
01650       ptopmrd = my.pmrd;
01651       if (my.pmrd == NULL)
01652          return SS_NO_MEMORY;
01653       memset((char *) my.pmrd, -1, 5 * MAX_EVENT_SIZE);
01654       my.pmh = (EVENT_HEADER *) my.pmrd;
01655    }
01656 
01657    /* initialize pertinent variables */
01658    my.recn = (DWORD) - 1;       /* physical record number */
01659    my.evtn = 0;
01660    return (YB_SUCCESS);
01661 }
01662 
01663 /*------------------------------------------------------------------*/
01664 INT yb_any_file_rclose(INT data_fmt)
01665 /********************************************************************
01666 Routine: external yb_any_file_rclose
01667 Purpose: Close a data file used for replay for the given data format
01668 Input:
01669 INT data_fmt :  YBOS or MIDAS 
01670 Output:
01671 none
01672 Function value:
01673 status : from lower function
01674 *******************************************************************/
01675 {
01676    switch (my.type) {
01677    case LOG_TYPE_TAPE:
01678    case LOG_TYPE_DISK:
01679       /* close file */
01680       if (my.zipfile) {
01681 #ifdef INCLUDE_ZLIB
01682          gzclose(filegz);
01683 #endif
01684       } else {
01685          if (my.handle != 0)
01686             close(my.handle);
01687       }
01688       break;
01689    }
01690    if (my.pmagta != NULL)
01691       free(my.pmagta);
01692    if (my.pyh != NULL)
01693       free(my.pyh);
01694    if (my.pylrl != NULL)
01695       free(my.pylrl);
01696    if (my.pmrd != NULL)
01697       free(my.pmrd);
01698    if (my.pmp != NULL)
01699       free(my.pmp);
01700    my.pylrl = NULL;
01701    my.pyh = NULL;
01702    my.pmagta = NULL;
01703    my.pmp = NULL;
01704    my.pmh = NULL;
01705    my.pmrd = NULL;
01706    return (YB_SUCCESS);
01707 }
01708 
01709 #ifdef INCLUDE_FTPLIB
01710 
01711 /* @ NOT TESTED @ */
01712 INT yb_ftp_open(char *destination, FTP_CON ** con)
01713 {
01714    INT status;
01715    short port = 0;
01716    char *token, host_name[HOST_NAME_LENGTH],
01717        user[32], pass[32], directory[256], file_name[256], file_mode[256];
01718 
01719    /* 
01720       destination should have the form:
01721       host, port, user, password, directory, run%05d.mid
01722     */
01723 
01724    /* break destination in components */
01725    token = strtok(destination, ",");
01726    if (token)
01727       strcpy(host_name, token);
01728 
01729    token = strtok(NULL, ", ");
01730    if (token)
01731       port = atoi(token);
01732 
01733    token = strtok(NULL, ", ");
01734    if (token)
01735       strcpy(user, token);
01736 
01737    token = strtok(NULL, ", ");
01738    if (token)
01739       strcpy(pass, token);
01740 
01741    token = strtok(NULL, ", ");
01742    if (token)
01743       strcpy(directory, token);
01744 
01745    token = strtok(NULL, ", ");
01746    if (token)
01747       strcpy(file_name, token);
01748 
01749    token = strtok(NULL, ", ");
01750    file_mode[0] = 0;
01751    if (token)
01752       strcpy(file_mode, token);
01753 
01754    status = ftp_login(con, host_name, port, user, pass, "");
01755    if (status >= 0)
01756       return status;
01757 
01758    status = ftp_chdir(*con, directory);
01759    if (status >= 0)
01760       return status;
01761 
01762    status = ftp_binary(*con);
01763    if (status >= 0)
01764       return status;
01765 
01766    if (file_mode[0]) {
01767       status = ftp_command(*con, "umask %s", file_mode, 200, 250, EOF);
01768       if (status >= 0)
01769          return status;
01770    }
01771 
01772    if (ftp_open_write(*con, file_name) >= 0)
01773       return (*con)->err_no;
01774 
01775    return SS_SUCCESS;
01776 }
01777 
01778 /* @ NOT TESTED @ */
01779 #endif
01780 
01781 /*------------------------------------------------------------------*/
01782 INT yb_any_file_wopen(INT type, INT data_fmt, char *filename, INT * hDev)
01783 /********************************************************************
01784 Routine: external yb_any_file_wopen
01785 Purpose: Open a data file for the given data format
01786 Input:
01787 INT type     :  Tape or Disk
01788 INT data_fmt :  YBOS or MIDAS
01789 char * filename : file to open
01790 Output:
01791 INT * hDev      : file handle
01792 Function value:
01793 status : from lower function
01794 *******************************************************************/
01795 {
01796    INT status = 0;
01797 
01798    if (type == LOG_TYPE_DISK)
01799       /* takes care of TapeLX/NT under ss_tape_open , DiskLX/NT here */
01800    {
01801       if (data_fmt == FORMAT_YBOS) {
01802          /* takes care of TapeLX/NT under ss_tape_open , DiskLX/NT there */
01803          status = ybos_logfile_open(type, filename, hDev);
01804       } else if (data_fmt == FORMAT_MIDAS) {
01805 #ifdef OS_WINNT
01806          *hDev =
01807              (int) CreateFile(filename, GENERIC_WRITE, FILE_SHARE_READ,
01808                               NULL, CREATE_ALWAYS,
01809                               FILE_ATTRIBUTE_NORMAL |
01810                               FILE_FLAG_WRITE_THROUGH | FILE_FLAG_SEQUENTIAL_SCAN, 0);
01811 #else
01812          *hDev = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE, 0644);
01813 #endif
01814          status = *hDev < 0 ? SS_FILE_ERROR : SS_SUCCESS;
01815       }
01816    } else if (type == LOG_TYPE_TAPE) {
01817       if (data_fmt == FORMAT_YBOS) {
01818          /* takes care of TapeLX/NT under ss_tape_open , DiskLX/NT there */
01819          status = ybos_logfile_open(type, filename, hDev);
01820       } else if (data_fmt == FORMAT_MIDAS)
01821          status = ss_tape_open(filename, O_WRONLY | O_CREAT | O_TRUNC, hDev);
01822    } else if (type == LOG_TYPE_FTP) {
01823 #ifdef INCLUDE_FTPLIB
01824       status = yb_ftp_open(filename, (FTP_CON **) & ftp_con);
01825       if (status != SS_SUCCESS) {
01826          *hDev = 0;
01827          return status;
01828       } else
01829          *hDev = 1;
01830 #else
01831       cm_msg(MERROR, "yb_any_file_wopen", "FTP support not included");
01832       return SS_FILE_ERROR;
01833 #endif
01834    }
01835 
01836    return status;
01837 }
01838 
01839 /*------------------------------------------------------------------*/
01840 INT yb_any_file_wclose(INT handle, INT type, INT data_fmt)
01841 /********************************************************************
01842 Routine: external yb_any_file_wclose
01843 Purpose: Close a data file used for replay for the given data format
01844 Input:
01845 INT data_fmt :  YBOS or MIDAS 
01846 Output:
01847 none
01848 Function value:
01849 status : from lower function
01850 *******************************************************************/
01851 {
01852    INT status;
01853    status = SS_SUCCESS;
01854    switch (type) {
01855    case LOG_TYPE_TAPE:
01856       /* writing EOF mark on tape Fonly */
01857       status = ss_tape_write_eof(handle);
01858       ss_tape_close(handle);
01859       break;
01860    case LOG_TYPE_DISK:
01861       /* close file */
01862       if (handle != 0)
01863 #ifdef OS_WINNT
01864          CloseHandle((HANDLE) handle);
01865 #else
01866          close(handle);
01867 #endif
01868       break;
01869    case LOG_TYPE_FTP:
01870 #ifdef INCLUDE_FTPLIB
01871       ftp_close(ftp_con);
01872       ftp_bye(ftp_con);
01873 #endif
01874       break;
01875    }
01876    if (status != SS_SUCCESS)
01877       return status;
01878    return (YB_SUCCESS);
01879 }
01880 
01881 /*------------------------------------------------------------------*/
01882 INT yb_any_dev_os_read(INT handle, INT type, void *prec, DWORD nbytes, DWORD * readn)
01883 /********************************************************************\
01884 Routine: yb_any_dev_os_read
01885 Purpose: read nbytes from the type device.
01886 Input:
01887 INT  handle        file handler
01888 INT  type          Type of device (TAPE or DISK)
01889 void * prec        pointer to the record
01890 DWORD nbytes       # of bytes to read
01891 Output:
01892 DWORD *readn       # of bytes read
01893 Function value:
01894 YB_DONE            No more record to read
01895 YB_SUCCESS         Ok
01896 \********************************************************************/
01897 {
01898    INT status;
01899    if (type == LOG_TYPE_DISK)
01900       /* --------- DISK ---------- */
01901    {
01902       *readn = read(handle, prec, nbytes);
01903       if (*readn <= 0)
01904          status = SS_FILE_ERROR;
01905       else
01906          status = SS_SUCCESS;
01907       return status;
01908    }
01909    /* --------- TAPE ---------- */
01910 #ifdef OS_UNIX
01911    else if (type == LOG_TYPE_TAPE) {
01912       *readn = read(handle, prec, nbytes);
01913       if (*readn <= 0)
01914          status = SS_FILE_ERROR;
01915       else
01916          status = SS_SUCCESS;
01917       return status;
01918    }
01919 #endif
01920 
01921 #ifdef OS_WINNT
01922    else if (type == LOG_TYPE_TAPE) {
01923       if (!ReadFile((HANDLE) handle, prec, nbytes, readn, NULL))
01924          status = GetLastError();
01925       else
01926          status = SS_SUCCESS;
01927       if (status == ERROR_NO_DATA_DETECTED)
01928          status = SS_END_OF_TAPE;
01929 
01930       return status;
01931    }
01932 #endif                          /* OS_WINNT */
01933    else
01934       return SS_SUCCESS;
01935 }
01936 
01937 /*------------------------------------------------------------------*/
01938 INT yb_any_dev_os_write(INT handle, INT type, void *prec, DWORD nbytes, DWORD * written)
01939 /********************************************************************\
01940 Routine: yb_any_dev_os_write
01941 Purpose: write nbytes to the device. This function is YBOS independent
01942 (NO magta stuff for disk)
01943 Input:
01944 INT  handle        file handler
01945 INT  type          Type of device (TAPE or DISK)
01946 void * prec        pointer to the record
01947 DWORD   nbytes     record length to be written
01948 Output:
01949 DWORD *written     # of written bytes
01950 Function value:
01951 INT status           # of written bytes or ERROR
01952 SS_FILE_ERROR      write error
01953 SS_SUCCESS         Ok
01954 \********************************************************************/
01955 {
01956    INT status;
01957    if (type == LOG_TYPE_DISK)
01958 #ifdef OS_WINNT
01959    {                            /* --------- DISK ---------- */
01960       WriteFile((HANDLE) handle, (char *) prec, nbytes, written, NULL);
01961       status = *written == nbytes ? SS_SUCCESS : SS_FILE_ERROR;
01962       return status;            /* return for DISK */
01963    }
01964 #else
01965    {                            /* --------- DISK ---------- */
01966       status = *written =
01967           write(handle, (char *) prec, nbytes) == nbytes ? SS_SUCCESS : SS_FILE_ERROR;
01968       return status;            /* return for DISK */
01969    }
01970 #endif
01971    else if (type == LOG_TYPE_TAPE) {    /* --------- TAPE ---------- */
01972 #ifdef OS_UNIX
01973       do {
01974          status = write(handle, (char *) prec, nbytes);
01975       } while (status == -1 && errno == EINTR);
01976       *written = status;
01977       if (*written != nbytes) {
01978          cm_msg(MERROR, "any_dev_os_write", strerror(errno));
01979          if (errno == EIO)
01980             return SS_IO_ERROR;
01981          if (errno == ENOSPC)
01982             return SS_NO_SPACE;
01983          else
01984             return SS_TAPE_ERROR;
01985       }
01986 #endif                          /* OS_UNIX */
01987 
01988 #ifdef OS_WINNT
01989       WriteFile((HANDLE) handle, (char *) prec, nbytes, written, NULL);
01990       if (*written != nbytes) {
01991          status = GetLastError();
01992          cm_msg(MERROR, "any_dev_os_write", "error %d", status);
01993          return SS_IO_ERROR;
01994       }
01995       return SS_SUCCESS;        /* return for TAPE */
01996 #endif                          /* OS_WINNT */
01997    } else if (type == LOG_TYPE_FTP)
01998 #ifdef INCLUDE_FTPLIB
01999    {
02000       *written =
02001           (DWORD) status =
02002           (INT) ftp_send(ftp_con->data, (char *) prec,
02003                          (int) nbytes) == (int) nbytes ? SS_SUCCESS : SS_FILE_ERROR;
02004       return status;
02005    }
02006 #else
02007    {
02008       cm_msg(MERROR, "ybos", "FTP support not included");
02009       return SS_IO_ERROR;
02010    }
02011 #endif
02012    return SS_SUCCESS;
02013 }
02014 
02015 /*------------------------------------------------------------------*/
02016 INT yb_any_physrec_get(INT data_fmt, void **precord, DWORD * readn)
02017 /********************************************************************\
02018 Routine: external yb_any_physrec_get
02019 Purpose: Retrieve a physical record for the given data format
02020 Input:
02021 INT data_fmt :  YBOS or MIDAS 
02022 Output:
02023 void ** precord     pointer to the record
02024 DWORD * readn       record length in bytes
02025 Function value:
02026 status : from lower function
02027 \********************************************************************/
02028 {
02029    *precord = my.pmp;
02030    if (data_fmt == FORMAT_MIDAS)
02031       return midas_physrec_get(*precord, readn);
02032    else if (data_fmt == FORMAT_YBOS)
02033       return ybos_physrec_get((DWORD **) precord, readn);
02034    else
02035       return YB_UNKNOWN_FORMAT;
02036 }
02037 
02038 /*------------------------------------------------------------------*/
02039 INT ybos_physrec_get(DWORD ** precord, DWORD * readn)
02040 /********************************************************************\
02041 Routine: ybos_physrec_get
02042 Purpose: read one physical YBOS record.
02043 The number of bytes to be read is fixed under YBOS.
02044 It is defined by my.size, In case of Disk file the magta
02045 stuff has to be read/rejected first.
02046 Input:
02047 void ** precord     pointer to the record
02048 DWORD * readn       record length in bytes
02049 Output:
02050 none
02051 Function value:
02052 YB_DONE            No more record to read
02053 YB_SUCCESS         Ok
02054 \********************************************************************/
02055 {
02056    INT status;
02057 
02058 #ifdef YBOS_VERSION_3_3
02059    if (my.magtafl) {
02060       /* skip 4 bytes from MAGTA header */
02061       if (!my.zipfile) {
02062          status = yb_any_dev_os_read(my.handle, my.type, my.pmagta, 4, readn);
02063          if (status != SS_SUCCESS)
02064             return (YB_DONE);
02065       } else {                  /* --------- GZIP ---------- */
02066 #ifdef INCLUDE_ZLIB
02067          status = gzread(filegz, (char *) my.pmagta, 4);
02068          if (status <= 0)
02069             return (YB_DONE);
02070 #endif
02071       }
02072    }
02073 #endif
02074 
02075    /* read full YBOS physical record */
02076    if (!my.zipfile) {
02077       status = yb_any_dev_os_read(my.handle, my.type, my.pyh, my.size << 2, readn);
02078       if (status != SS_SUCCESS)
02079          return (YB_DONE);
02080    } else {
02081 #ifdef INCLUDE_ZLIB
02082       status = gzread(filegz, (char *) my.pyh, my.size << 2);
02083       if (status <= 0)
02084          return (YB_DONE);
02085 #endif
02086    }
02087 
02088 #ifdef YBOS_VERSION_3_3
02089    /* check if header make sense for MAGTA there is extra stuff to get rid off */
02090    if ((!my.magtafl) && (*((DWORD *) my.pyh) == 0x00000004)) {
02091       /* set MAGTA flag */
02092       my.magtafl = TRUE;
02093       /* BOT of MAGTA skip record */
02094       if (!my.zipfile) {
02095          status = yb_any_dev_os_read(my.handle, my.type, my.pmagta, 8, readn);
02096          if (status != SS_SUCCESS)
02097             return (YB_DONE);
02098       } else {
02099 #ifdef INCLUDE_ZLIB
02100          status = gzread(filegz, (char *) my.pmagta, 8);
02101          if (status <= 0)
02102             return (YB_DONE);
02103 #endif
02104       }
02105 
02106       /* read full YBOS physical record */
02107       if (!my.zipfile) {
02108          status = yb_any_dev_os_read(my.handle, my.type, my.pyh, my.size << 2, readn);
02109          if (status != SS_SUCCESS)
02110             return (YB_DONE);
02111       } else {
02112 #ifdef INCLUDE_ZLIB
02113          status = gzread(filegz, (char *) my.pyh, my.size << 2);
02114          if (status <= 0)
02115             return (YB_DONE);
02116 #endif
02117       }
02118    }
02119 #endif
02120 
02121    /* move current ptr of newly phys rec to first event */
02122    if ((my.pyh)->offset == 0) {
02123       /* no new event ==> full phys rec is continuation of the previous event
02124          leave pointer to continuation */
02125       my.pyrd = (DWORD *) my.pyh + (my.pyh)->offset;
02126    } else {
02127       /* new event in physical record 
02128          leave pointer to plrl */
02129       my.pyrd = (DWORD *) my.pyh + (my.pyh)->offset;
02130    }
02131    /* count blocks */
02132    my.recn++;
02133 
02134    *precord = (DWORD *) (my.pyh);
02135 
02136    return (YB_SUCCESS);
02137 }
02138 
02139 /*------------------------------------------------------------------*/
02140 INT midas_physrec_get(void *prec, DWORD * readn)
02141 /********************************************************************\
02142 Routine: midas_physrec_get
02143 Purpose: read one physical record.from a MIDAS run
02144 This is a "fake" physical record as Midas is
02145 not block structured. This function is used for
02146 reading a my.size record size. The return readn if different
02147 then my.size, will indicate a end of run. An extra read will
02148 indicate an eof.
02149 
02150 Input:
02151 void * prec        pointer to the record
02152 Output:
02153 DWORD *readn       retrieve number of bytes
02154 Function value:
02155 YB_DONE            No more record to read
02156 YB_SUCCESS         Ok
02157 \********************************************************************/
02158 {
02159    INT status = 0;
02160 
02161    /* read one block of data */
02162    if (!my.zipfile) {
02163       status = yb_any_dev_os_read(my.handle, my.type, prec, my.size, readn);
02164    } else {
02165 #ifdef INCLUDE_ZLIB
02166       *readn = gzread(filegz, (char *) prec, my.size);
02167       if (*readn <= 0)
02168          status = SS_FILE_ERROR;
02169       else
02170          status = SS_SUCCESS;
02171 #endif
02172    }
02173 
02174    if (status != SS_SUCCESS) {
02175       return (YB_DONE);
02176    } else {
02177       /* count blocks */
02178       my.recn++;
02179       return (YB_SUCCESS);
02180    }
02181 }
02182 
02183 /*------------------------------------------------------------------*/
02184 INT yb_any_log_write(INT handle, INT data_fmt, INT type, void *prec, DWORD nbytes)
02185 /********************************************************************\
02186 Routine: external yb_any_log_write
02187 Purpose: Write a physical record to the out device, takes care of the
02188 magta under YBOS.
02189 
02190 Input:
02191 void handle   : file handle
02192 INT data_fmt  : YBOS or MIDAS 
02193 INT type      : Tape or disk 
02194 void *prec    : record pointer
02195 DWORD nbytes  : record length to be written
02196 Output:
02197 none
02198 Function value:
02199 status : from lower function  SS_SUCCESS, SS_FILE_ERROR
02200 \********************************************************************/
02201 {
02202    INT status;
02203    DWORD written;
02204 
02205 #ifdef YBOS_VERSION_3_3
02206    if ((type == LOG_TYPE_DISK) && (data_fmt == FORMAT_YBOS)) {  /* add the magta record if going to disk */
02207       status =
02208           yb_any_dev_os_write(handle, type,
02209                               (char *) ((DWORD *) (magta + 2)), 4, &written);
02210       if (status != SS_SUCCESS)
02211          return status;
02212    }
02213 #endif
02214    /* write record */
02215    status = yb_any_dev_os_write(handle, type, prec, nbytes, &written);
02216    return status;
02217 }
02218 
02219 /*------------------------------------------------------------------*/
02220 INT yb_any_physrec_skip(INT data_fmt, INT bl)
02221 /********************************************************************\
02222 Routine: external yb_any_physrec_skip
02223 Purpose: Skip physical record until block = bl for the given data
02224 format, Under midas the skip is an event as no physical 
02225 record is present under that format,
02226 Input:
02227 INT data_fmt :  YBOS or MIDAS 
02228 INT bl:         block number (-1==all, 0 = first block)
02229 in case of MIDAS the bl represent an event
02230 Output:
02231 none
02232 Function value:
02233 status : from lower function
02234 \********************************************************************/
02235 {
02236    INT status;
02237 
02238    if (data_fmt == FORMAT_MIDAS) {
02239       status = midas_event_skip(bl);
02240       return YB_SUCCESS;
02241    } else if (data_fmt == FORMAT_YBOS)
02242       return ybos_physrec_skip(bl);
02243    else
02244       return YB_UNKNOWN_FORMAT;
02245 }
02246 
02247 /*------------------------------------------------------------------*/
02248 INT ybos_physrec_skip(INT bl)
02249 /********************************************************************\
02250 Routine: ybos_physrec_skip
02251 Purpose: skip physical record on a YBOS file.
02252 The physical record size is fixed (see ybos.h)
02253 Input:
02254 INT     bl            physical record number. (start at 0)
02255 if bl = -1 : skip skiping
02256 Output:
02257 none
02258 Function value:
02259 YB_SUCCESS        Ok
02260 \********************************************************************/
02261 {
02262    INT status;
02263    DWORD *prec, size;
02264 
02265    if (bl == -1) {
02266       if ((status = ybos_physrec_get(&prec, &size)) == YB_SUCCESS)
02267          return status;
02268    }
02269    while (ybos_physrec_get(&prec, &size) == YB_SUCCESS) {
02270       if ((INT) (my.pyh)->rec_num != bl) {
02271          printf("Skipping physical record_# ... ");
02272          printf("%ld \r", (my.pyh)->rec_num);
02273          fflush(stdout);
02274       } else {
02275          printf("\n");
02276          return YB_SUCCESS;
02277       }
02278    }
02279    return YB_DONE;
02280 }
02281 
02282 /*------------------------------------------------------------------*/
02283 INT midas_event_skip(INT evtn)
02284 /********************************************************************\
02285 Routine: midas_event_skip
02286 Purpose: skip event on a MIDAS file.
02287 Input:
02288 INT     evtn          event record number. (start at 0)
02289 if evt = -1 : skip skiping
02290 Output:
02291 none
02292 Function value:
02293 YB_SUCCESS        Ok
02294 \********************************************************************/
02295 {
02296    void *pevent;
02297    DWORD size;
02298 
02299    size = MAX_EVENT_SIZE;
02300    if (evtn == -1) {
02301       /*    if(midas_event_get(&pevent, &size) == YB_SUCCESS) */
02302       return YB_SUCCESS;
02303    }
02304    while (midas_event_get(&pevent, &size) == YB_SUCCESS) {
02305       if ((INT) my.evtn < evtn) {
02306          printf("Skipping event_# ... ");
02307          printf("%ld \r", my.evtn);
02308          fflush(stdout);
02309       } else {
02310          printf("\n");
02311          return YB_SUCCESS;
02312       }
02313    }
02314    return YB_DONE;
02315 }
02316 
02317 /*------------------------------------------------------------------*/
02318 INT yb_any_physrec_display(INT data_fmt)
02319 /********************************************************************\
02320 Routine: external yb_any_physrec_display
02321 Purpose: Display the physical record of the current record 
02322 for the given data format.
02323 Not possible for MIDAS as no physical record structure
02324 Input:
02325 INT data_fmt :  YBOS or MIDAS 
02326 Output:
02327 none
02328 Function value:
02329 status          Lower function
02330 \********************************************************************/
02331 {
02332    INT bz, j, i, k;
02333    DWORD *prec;
02334 
02335    if (data_fmt == FORMAT_MIDAS) {
02336       printf(">>> No physical record structure for Midas format <<<\n");
02337       return YB_DONE;
02338    } else if (data_fmt == FORMAT_YBOS) {
02339       yb_any_all_info_display(D_RECORD);
02340       bz = (my.pyh)->rec_size + 1;
02341       /* adjust local pointer to top of record to include record header */
02342       prec = (DWORD *) (my.pyh);
02343       k = (my.pyh)->rec_num;
02344       for (i = 0; i < bz; i += NLINE) {
02345          printf("R(%d)[%d] = ", k, i);
02346          for (j = 0; j < NLINE; j++) {
02347             if (i + j < bz) {
02348                printf("%8.8lx ", *prec);
02349                prec++;
02350             }
02351          }
02352          printf("\n");
02353       }
02354       return (YB_SUCCESS);
02355    } else
02356       return YB_UNKNOWN_FORMAT;
02357 }
02358 
02359 /*------------------------------------------------------------------*/
02360 INT yb_any_all_info_display(INT what)
02361 /********************************************************************\
02362 Routine: yb_any_all_info_display
02363 Purpose: display on screen all the info about "what".
02364 Input:
02365 INT     what              type of display.
02366 Output:
02367 none
02368 Function value:
02369 INT                 YB_SUCCESS
02370 YB_DONE
02371 \********************************************************************/
02372 {
02373    if (my.fmt == FORMAT_YBOS) {
02374       DWORD bz, hyl, ybn, of;
02375 
02376       bz = (my.pyh)->rec_size;
02377       hyl = (my.pyh)->header_length;
02378       ybn = (my.pyh)->rec_num;
02379       of = (my.pyh)->offset;
02380       switch (what) {
02381       case D_RECORD:
02382       case D_HEADER:
02383          printf("rec#%ld- ", my.recn);
02384          printf("%5ldbz %5ldhyl %5ldybn %5ldof\n", bz, hyl, ybn, of);
02385          break;
02386       case D_EVTLEN:
02387          printf("rec#%ld- ", my.recn);
02388          printf("%5ldbz %5ldhyl %5ldybn %5ldof ", bz, hyl, ybn, of);
02389          printf("%5ldel/x%lx %5ldev\n", my.evtlen, my.evtlen, my.evtn);
02390          break;
02391       }
02392    } else if (my.fmt == FORMAT_MIDAS) {
02393       DWORD mbn, run, ser;
02394       WORD id, msk;
02395       mbn = my.evtn;
02396       run = my.runn;
02397       id = my.pmh->event_id;
02398       msk = my.pmh->trigger_mask;
02399       ser = my.pmh->serial_number;
02400       switch (what) {
02401       case D_RECORD:
02402       case D_HEADER:
02403          printf(">>> No physical record structure for Midas format <<<\n");
02404          return YB_DONE;
02405          break;
02406       case D_EVTLEN:
02407          printf("Evt#%ld- ", my.evtn);
02408          printf("%lirun 0x%4.4uxid 0x%4.4uxmsk %5ldmevt#", run, id, msk, mbn);
02409          printf("%5ldel/x%lx %5ldserial\n", my.evtlen, my.evtlen, ser);
02410          break;
02411       }
02412    }
02413    return YB_SUCCESS;
02414 }
02415 
02416 /*------------------------------------------------------------------*/
02417 INT yb_any_event_swap(INT data_fmt, void *pevent)
02418 /********************************************************************\
02419 Routine: external yb_any_event_swap
02420 Purpose: Swap an event from the given data format.
02421 Input:
02422 INT data_fmt  : YBOS or MIDAS 
02423 void * pevent : pointer to either plrl or pheader
02424 Output:
02425 none
02426 Function value:
02427 status :  from the lower function
02428 \********************************************************************/
02429 {
02430    INT status;
02431    BANK_HEADER *pbh;
02432 
02433    if (data_fmt == FORMAT_MIDAS) {
02434       if ((((EVENT_HEADER *) pevent)->event_id == EVENTID_BOR) ||
02435           (((EVENT_HEADER *) pevent)->event_id == EVENTID_EOR) ||
02436           (((EVENT_HEADER *) pevent)->event_id == EVENTID_MESSAGE))
02437          return SS_SUCCESS;
02438       pbh = (BANK_HEADER *) (((EVENT_HEADER *) pevent) + 1);
02439       status = bk_swap(pbh, FALSE);
02440       return status == CM_SUCCESS ? YB_EVENT_NOT_SWAPPED : YB_SUCCESS;
02441    } else if (data_fmt == FORMAT_YBOS) {
02442       status = ybos_event_swap((DWORD *) pevent);
02443       return status == YB_EVENT_NOT_SWAPPED ? YB_SUCCESS : status;
02444    }
02445 
02446    return YB_UNKNOWN_FORMAT;
02447 }
02448 
02449 /*------------------------------------------------------------------*/
02450 INT ybos_event_swap(DWORD * plrl)
02451 /********************************************************************\
02452 Routine: ybos_event_swap
02453 Purpose: byte swap the entire YBOS event if necessary.
02454 chekc necessity of swapping by looking at the 
02455 bank type being < MAX_BKTYPE 
02456 Input:
02457 DWORD * plrl           pointer to the YBOS event
02458 Output:
02459 none
02460 Function value:
02461 YB_SUCCESS             Event has been swapped
02462 YB_EVENT_NOT_SWAPPED   Event has been not been swapped
02463 YB_SWAP_ERROR          swapping error
02464 \********************************************************************/
02465 {
02466    DWORD *pevt, *pnextb, *pendevt;
02467    DWORD bank_length, bank_type;
02468 
02469    /* check if event has to be swapped */
02470    if ((((YBOS_BANK_HEADER *) (plrl + 1))->type) < MAX_BKTYPE)
02471       return (YB_EVENT_NOT_SWAPPED);
02472 
02473    /* swap LRL */
02474    DWORD_SWAP(plrl);
02475    pevt = plrl + 1;
02476 
02477    /* end of event pointer */
02478    pendevt = pevt + *plrl;
02479 
02480    /* scan event */
02481    while (pevt < pendevt) {
02482       /* swap YBOS bank header for sure */
02483       /* bank name doesn't have to be swapped as it's an ASCII coded */
02484       pevt++;                   /* bank name */
02485 
02486       DWORD_SWAP(pevt);         /* bank number */
02487       pevt++;
02488 
02489       DWORD_SWAP(pevt);         /* bank index */
02490       pevt++;
02491 
02492       DWORD_SWAP(pevt);         /* bank length */
02493       bank_length = *pevt++;
02494 
02495       DWORD_SWAP(pevt);         /* bank type */
02496       bank_type = *pevt++;
02497 
02498       /* pevt left pointing at first data in bank */
02499 
02500       /* pointer to next bank (-1 due to type inclided in length #$%@ */
02501       pnextb = pevt + bank_length - 1;
02502 
02503       switch (bank_type) {
02504       case D8_BKTYPE:
02505          while ((BYTE *) pevt < (BYTE *) pnextb) {
02506             QWORD_SWAP(pevt);
02507             pevt = (DWORD *) (((double *) pevt) + 1);
02508          }
02509          break;
02510       case I4_BKTYPE:
02511       case F4_BKTYPE:
02512          while ((BYTE *) pevt < (BYTE *) pnextb) {
02513             DWORD_SWAP(pevt);
02514             pevt++;
02515          }
02516          break;
02517       case I2_BKTYPE:
02518          while ((BYTE *) pevt < (BYTE *) pnextb) {
02519             WORD_SWAP(pevt);
02520             pevt = (DWORD *) (((WORD *) pevt) + 1);
02521          }
02522          break;
02523       case I1_BKTYPE:
02524       case A1_BKTYPE:
02525          pevt = pnextb;
02526          break;
02527       default:
02528          printf("ybos_swap_event-E- Unknown bank type %li\n", bank_type);
02529          return (YB_SWAP_ERROR);
02530          break;
02531       }
02532    }
02533    return (YB_SUCCESS);
02534 }
02535 
02536 /*------------------------------------------------------------------*/
02537 INT yb_any_event_get(INT data_fmt, void **pevent, DWORD * readn)
02538 /********************************************************************\
02539 Routine: external yb_any_event_get
02540 Purpose: Retrieve an event from the given data format.
02541 Input:
02542 INT data_fmt :  YBOS or MIDAS 
02543 void ** pevent : either plrl or pheader
02544 Output:
02545 DWORD * readn : number of bytes read
02546 Function value:
02547 status : from lower function
02548 \********************************************************************/
02549 {
02550    INT status = 0;
02551 
02552    *pevent = NULL;
02553    if (data_fmt == FORMAT_MIDAS)
02554       status = midas_event_get(pevent, readn);
02555    else if (data_fmt == FORMAT_YBOS)
02556       status = ybos_event_get((DWORD **) pevent, readn);
02557    return (status);
02558 }
02559 
02560 /*------------------------------------------------------------------*/
02561 INT ybos_event_get(DWORD ** plrl, DWORD * readn)
02562 /********************************************************************\
02563 Routine: ybos_event_get
02564 Purpose: read one YBOS event.
02565 detect the end of run by checking the *plrl content (-1)
02566 Input:
02567 Output:
02568 DWORD ** plrl      points to LRL valid full YBOS event
02569 DWORD * readn      event size in Bytes 
02570 Function value:
02571 YB_DONE           No more record to read
02572 YB_SUCCESS        Ok
02573 \********************************************************************/
02574 {
02575    DWORD size, fpart, lpart, evt_length;
02576    DWORD *ptmp, *prec;
02577    INT status;
02578 
02579    /* detect end of run (no more events) 
02580       by checking the *pyrd == -1 */
02581    if ((INT) (*my.pyrd) == -1)
02582       return YB_DONE;
02583    /* extract event to local event area
02584       event may not be complete if larger then physical record size
02585       will be taken care below, ADD the lrl  */
02586    evt_length = *(my.pyrd) + 1;
02587    memcpy((char *) my.pylrl, (char *) my.pyrd, evt_length << 2);
02588 
02589    /* extract lrl in I*4 and include itself (lrl) */
02590 
02591    /* stop if LRL  = -1 ... I don't think it is necessary but I leave it in for now
02592       or forever... */
02593    if (evt_length - 1 == -1)
02594       return (YB_DONE);
02595 
02596    /* check if event cross physical record boundary */
02597    if ((my.pyrd + evt_length) >= (DWORD *) my.pyh + my.size) {
02598       /* upcomming event crosses block, then first copy first part of event */
02599       /* compute max copy for first part of event */
02600       fpart = (DWORD *) my.pyh + my.size - my.pyrd;
02601       memcpy((char *) my.pylrl, (char *) my.pyrd, fpart << 2);
02602 
02603       /* adjust temporary evt pointer all in I*4 */
02604       ptmp = my.pylrl + fpart;
02605 
02606       if ((evt_length - fpart) == 0) {
02607          /* get next physical record */
02608          if ((status = ybos_physrec_get(&prec, &size)) != YB_SUCCESS)
02609             return (status);
02610          my.pyrd = (DWORD *) my.pyh + my.pyh->header_length;
02611       } else {
02612          while ((evt_length - fpart) > 0) {
02613             lpart = evt_length - fpart;
02614             if (lpart > (YBOS_PHYREC_SIZE - YBOS_HEADER_LENGTH))
02615                lpart = (YBOS_PHYREC_SIZE - YBOS_HEADER_LENGTH);
02616 
02617             /* get next physical record */
02618             if ((status = ybos_physrec_get(&prec, &size)) != YB_SUCCESS)
02619                return (status);
02620 
02621             /* pyrd is left at the next lrl but here we comming from
02622                a cross boundary request so read just the pyrd to 
02623                pyh+header_length */
02624             my.pyrd = (DWORD *) my.pyh + my.pyh->header_length;
02625             /* now copy remaining from temporary pointer */
02626             memcpy((char *) ptmp, (char *) my.pyrd, lpart << 2);
02627 
02628             /* adjust pointer to next valid data (LRL) 
02629                should be equivalent to pyh+pyh->offset */
02630             my.pyrd += lpart;
02631             fpart += lpart;
02632             ptmp += lpart;
02633          }
02634       }
02635       if (my.pyrd != (DWORD *) my.pyh + my.pyh->offset) {
02636          printf(" event misalignment !! %p  %p \n",
02637                 my.pyrd, (DWORD *) my.pyh + my.pyh->offset);
02638          printf("Event crossed boundary: length %ld\n", evt_length);
02639          my.pyrd = (DWORD *) my.pyh + my.pyh->offset;
02640       }
02641 
02642    } else {
02643       /* adjust pointer to next valid data (LRL) */
02644       my.pyrd += evt_length;
02645    }
02646    /* count event */
02647    my.evtn++;
02648 
02649   /*-PAA- Dec99 Danny adjust event size in I*4 */
02650    my.evtlen = evt_length;
02651    /* in bytes for the world */
02652    *readn = my.evtlen << 2;
02653    *plrl = (DWORD *) my.pylrl;
02654    return (YB_SUCCESS);
02655 }
02656 
02657 /*------------------------------------------------------------------*/
02658 INT midas_event_get(void **pevent, DWORD * readn)
02659 /********************************************************************\
02660 Routine: midas_event_get
02661 Purpose: read one MIDAS event.
02662 Will detect:
02663 The first pass in getting the record number being -1
02664 The last pass in checking the midas_physrec_get() readn
02665 being different then the my.size then flushing the current
02666 buffer until pointer goes beyond last event.
02667 Input:
02668 void ** pevent     points to MIDAS HEADER 
02669 Output:
02670 DWORD * readn      event size in bytes (MIDAS)
02671 Function value:
02672 YB_DONE           No more record to read
02673 YB_SUCCESS        Ok
02674 \********************************************************************/
02675 {
02676    INT status, leftover;
02677    DWORD fpart;
02678    static DWORD size = 0;
02679 
02680    /* save pointer */
02681    *pevent = (char *) my.pmh;
02682    if (size == 0)
02683       size = my.size;
02684 
02685    /* first time in get physrec once */
02686    if (my.recn == -1) {
02687       status = midas_physrec_get((void *) my.pmp, &size);
02688       if (status != YB_SUCCESS)
02689          return (YB_DONE);
02690    }
02691 
02692   /*-PAA- Jul 12/2002
02693     if (((my.pmp+size) - (char *)my.pme) == 0)
02694         return (YB_DONE);
02695   */
02696 
02697    /* copy header only */
02698    if (((my.pmp + size) - (char *) my.pme) < sizeof(EVENT_HEADER)) {
02699       fpart = (my.pmp + my.size) - (char *) my.pme;
02700       memcpy(my.pmh, my.pme, fpart);
02701       my.pmh = (EVENT_HEADER *) (((char *) my.pmh) + fpart);
02702       leftover = sizeof(EVENT_HEADER) - fpart;
02703       status = midas_physrec_get((void *) my.pmp, &size);
02704       if (status != YB_SUCCESS)
02705          return (YB_DONE);
02706       memset(my.pmp + size, -1, my.size - size);
02707       my.pme = (EVENT_HEADER *) my.pmp;
02708       memcpy(my.pmh, my.pme, leftover);
02709       my.pme = (EVENT_HEADER *) (((char *) my.pme) + leftover);
02710       my.pmh = (EVENT_HEADER *) * pevent;
02711    } else {
02712       memcpy(my.pmh, my.pme, sizeof(EVENT_HEADER));
02713       my.pme = (EVENT_HEADER *) (((char *) my.pme) + sizeof(EVENT_HEADER));
02714    }
02715    /* leave with pmh  to destination header
02716       pmrd to destination event (pmh+1)
02717       pme  to source event
02718     */
02719    my.pmrd = (char *) (my.pmh + 1);
02720 
02721    /* check for end of file */
02722    if (my.pmh->event_id == -1)
02723       return YB_DONE;
02724 
02725    /* copy event (without header) */
02726    leftover = my.pmh->data_size;
02727 
02728    /* check for block crossing */
02729    while (((my.pmp + size) - (char *) my.pme) < leftover) {
02730       fpart = (my.pmp + my.size) - (char *) my.pme;
02731       memcpy(my.pmrd, my.pme, fpart);
02732       my.pmrd += fpart;
02733       leftover -= fpart;
02734       status = midas_physrec_get((void *) my.pmp, &size);
02735       if (status != YB_SUCCESS)
02736          return (YB_DONE);
02737       memset(my.pmp + size, -1, my.size - size);
02738       my.pme = (EVENT_HEADER *) my.pmp;
02739    }
02740 
02741    /* copy left over or full event if no Xing */
02742    *readn = my.evtlen = my.pmh->data_size + sizeof(EVENT_HEADER);
02743    memcpy(my.pmrd, my.pme, leftover);
02744    my.pme = (EVENT_HEADER *) (((char *) my.pme) + leftover);
02745    my.evtn++;
02746    return YB_SUCCESS;
02747 }
02748 
02749 /*------------------------------------------------------------------*/
02750 void yb_any_event_display(void *pevent, INT data_fmt, INT dsp_mode, INT dsp_fmt)
02751 /********************************************************************\
02752 Routine: external yb_any_event_display
02753 Purpose: display on screen the YBOS event in either RAW or YBOS mode
02754 and in either Decimal or Hexadecimal.
02755 Input:
02756 void *  pevent     pointer to either plrl or pheader.
02757 INT     data_fmt   uses the YBOS or MIDAS event structure
02758 INT     dsp_mode   display in RAW or Bank mode
02759 INT     dsp_fmt    display format (DSP_DEC/HEX)
02760 Output:
02761 none
02762 Function value:
02763 none
02764 \********************************************************************/
02765 {
02766    if (dsp_mode == DSP_RAW)
02767       yb_any_raw_event_display(pevent, data_fmt, dsp_fmt);
02768    else if (dsp_mode == DSP_BANK)
02769       yb_any_bank_event_display(pevent, data_fmt, dsp_fmt);
02770    else
02771       printf("yb_any_event_display- Unknown format:%i\n", dsp_fmt);
02772    return;
02773 }
02774 
02775 /*------------------------------------------------------------------*/
02776 void yb_any_raw_event_display(void *pevent, INT data_fmt, INT dsp_fmt)
02777 /********************************************************************\
02778 Routine: yb_any_raw_event_display
02779 Purpose: display on screen the RAW data of either YBOS or MIDAS format.
02780 Input:
02781 DWORD *  pevent         points to either plrl or pheader
02782 INT     data_fmt        uses the YBOS or MIDAS event structure
02783 INT      dsp_fmt        display format (DSP_DEC/HEX)
02784 Output:
02785 none
02786 Function value:
02787 none
02788 \********************************************************************/
02789 {
02790    DWORD lrl = 0, *pevt = NULL, j, i, total = 0;
02791 
02792    if (data_fmt == FORMAT_YBOS) {
02793       lrl = *((DWORD *) (pevent)) + 1;  /* include itself */
02794       pevt = (DWORD *) pevent;  /* local copy starting from the plrl */
02795    } else if (data_fmt == FORMAT_MIDAS) {
02796       lrl = ((((EVENT_HEADER *) pevent)->data_size) + sizeof(EVENT_HEADER)) / sizeof(DWORD);    /* in I*4 for raw including the header */
02797       pevt = (DWORD *) pevent;  /* local copy starting from the pheader */
02798    }
02799 
02800    for (i = 0; i < lrl; i += NLINE) {
02801       printf("%6.0ld->: ", total);
02802       for (j = 0; j < NLINE; j++) {
02803          if ((i + j) < lrl) {
02804             if (dsp_fmt == DSP_DEC)
02805                printf("%8.li ", *pevt);
02806             else
02807                printf("%8.8lx ", *pevt);
02808             pevt++;
02809          }
02810       }
02811       total += NLINE;
02812       printf("\n");
02813    }
02814 }
02815 
02816 /*------------------------------------------------------------------*/
02817 void yb_any_bank_event_display(void *pevent, INT data_fmt, INT dsp_fmt)
02818 /********************************************************************\
02819 Routine: ybos_bank_event_display
02820 Purpose: display on screen the event header, bank list and bank content
02821 for either ybos or midas format. In case of ybos check is EVID is 
02822 present if so extract its content (see macro ybos.h)
02823 Input:
02824 void * pevent          points to either plrl or pheader
02825 INT     data_fmt       uses the YBOS or MIDAS event structure
02826 INT     dsp_fmt        display format (DSP_DEC/HEX)
02827 Output:
02828 none
02829 Function value:
02830 none
02831 \********************************************************************/
02832 {
02833    char banklist[YB_STRING_BANKLIST_MAX];
02834    YBOS_BANK_HEADER *pybk;
02835    DWORD *pdata;
02836    DWORD bklen, bktyp;
02837    BANK_HEADER *pbh;
02838    BANK *pmbk;
02839    BANK32 *pmbk32;
02840    EVENT_HEADER *pheader;
02841    INT status;
02842 
02843    if (data_fmt == FORMAT_YBOS) {
02844       /* event header --> No event header in YBOS */
02845 
02846       /* bank list */
02847       status = ybk_list((DWORD *) pevent, banklist);
02848       printf("#banks:%i - Bank list:-%s-\n", status, banklist);
02849 
02850       /* check if EVID is present if so display its content */
02851       if ((status =
02852            ybk_find((DWORD *) pevent, "EVID", &bklen, &bktyp,
02853                     (void **) &pybk)) == YB_SUCCESS) {
02854          pdata = (DWORD *) ((YBOS_BANK_HEADER *) pybk + 1);
02855          printf
02856              ("--------- EVID --------- Event# %li ------Run#:%li--------\n",
02857               YBOS_EVID_EVENT_NB(pdata), YBOS_EVID_RUN_NUMBER(pdata));
02858          printf
02859              ("Evid:%4.4x- Mask:%4.4x- Serial:%li- Time:0x%lx- Dsize:%li/0x%lx",
02860               (WORD) YBOS_EVID_EVENT_ID(pdata), (WORD) YBOS_EVID_TRIGGER_MASK(pdata)
02861               , YBOS_EVID_SERIAL(pdata), YBOS_EVID_TIME(pdata)
02862               , ((YBOS_BANK_HEADER *) pybk)->length, ((YBOS_BANK_HEADER *) pybk)->length);
02863       }
02864 
02865       /* display bank content */
02866       pybk = NULL;
02867       while ((ybk_iterate((DWORD *) pevent, &pybk, (void **) &pdata) >= 0)
02868              && (pybk != NULL))
02869          ybos_bank_display(pybk, dsp_fmt);
02870    } else if (data_fmt == FORMAT_MIDAS) {
02871       /* skip these special events (NO bank structure) */
02872       pheader = (EVENT_HEADER *) pevent;
02873       if (pheader->event_id == EVENTID_BOR ||
02874           pheader->event_id == EVENTID_EOR || pheader->event_id == EVENTID_MESSAGE)
02875          return;
02876 
02877       /* event header */
02878       printf
02879           ("Evid:%4.4x- Mask:%4.4x- Serial:%li- Time:0x%lx- Dsize:%li/0x%lx",
02880            (WORD) pheader->event_id, (WORD) pheader->trigger_mask,
02881            pheader->serial_number, pheader->time_stamp, pheader->data_size,
02882            pheader->data_size);
02883 
02884       /* check if format is MIDAS or FIXED */
02885       pbh = (BANK_HEADER *) (pheader + 1);
02886       if ((pbh->data_size + 8) == pheader->data_size) {
02887          /* bank list */
02888          status = bk_list((BANK_HEADER *) (pheader + 1), banklist);
02889          printf("\n#banks:%i - Bank list:-%s-\n", status, banklist);
02890 
02891          /* display bank content */
02892          if (bk_is32(pbh)) {
02893             pmbk32 = NULL;
02894             do {
02895                bk_iterate32(pbh, &pmbk32, &pdata);
02896                if (pmbk32 != NULL)
02897                   midas_bank_display32(pmbk32, dsp_fmt);
02898             } while (pmbk32 != NULL);
02899          } else {
02900             pmbk = NULL;
02901             do {
02902                bk_iterate(pbh, &pmbk, &pdata);
02903                if (pmbk != NULL)
02904                   midas_bank_display(pmbk, dsp_fmt);
02905             } while (pmbk != NULL);
02906          }
02907       } else {
02908          printf("\nFIXED event with Midas Header\n");
02909          yb_any_raw_event_display(pevent, data_fmt, dsp_fmt);
02910       }
02911    }
02912    return;
02913 }
02914 
02915 /*------------------------------------------------------------------*/
02916 void yb_any_bank_display(void *pmbh, void *pbk, INT data_fmt, INT dsp_mode, INT dsp_fmt)
02917 /********************************************************************\
02918 Routine: external yb_any_bank_display
02919 Purpose: display on screen the given bank.
02920 Input:
02921 void * pbk          pointer to the bank
02922 INT  data_fmt       YBOS or MIDAS
02923 INT  dsp_mode       display mode (RAW/BANK)
02924 INT  dsp_fmt        display format (DSP_DEC/HEX)
02925 Output:             
02926 none
02927 Function value:
02928 none
02929 \********************************************************************/
02930 {
02931    if (dsp_mode == DSP_RAW)
02932       yb_any_raw_bank_display(pbk, data_fmt, dsp_fmt);
02933    else {
02934       if (data_fmt == FORMAT_MIDAS) {
02935          if (bk_is32(pmbh))
02936             midas_bank_display32((BANK32 *) pbk, dsp_fmt);
02937          else
02938             midas_bank_display((BANK *) pbk, dsp_fmt);
02939       } else if (data_fmt == FORMAT_YBOS)
02940          ybos_bank_display((YBOS_BANK_HEADER *) pbk, dsp_fmt);
02941    }
02942    return;
02943 }
02944 
02945 /*------------------------------------------------------------------*/
02946 void yb_any_raw_bank_display(void *pbank, INT data_fmt, INT dsp_fmt)
02947 /********************************************************************\
02948 Routine: yb_any_raw_bank_display
02949 Purpose: display on screen the RAW data of a given YBOS/MIDAS bank.
02950 Input:
02951 void  * pbank          pointer to the bank name
02952 INT     data_fmt       uses the YBOS or MIDAS event structure
02953 INT     dsp_fmt        display format (DSP_DEC/HEX)
02954 Output:
02955 none
02956 Function value:
02957 none
02958 \********************************************************************/
02959 {
02960    DWORD *pdata = NULL, lrl = 0, j, i;
02961 
02962    if (data_fmt == FORMAT_YBOS) {
02963       lrl = (((YBOS_BANK_HEADER *) pbank)->length) - 1;
02964       pdata = (DWORD *) (((YBOS_BANK_HEADER *) pbank) + 1);
02965    } else if (data_fmt == FORMAT_MIDAS) {
02966       lrl = ((BANK *) pbank)->data_size >> 2;   /* in DWORD */
02967       pdata = (DWORD *) ((BANK *) (pbank) + 1);
02968    }
02969 
02970    for (i = 0; i < lrl; i += NLINE) {
02971       j = 0;
02972       printf("\n%4li-> ", i + j + 1);
02973       for (j = 0; j < NLINE; j++) {
02974          if ((i + j) < lrl) {
02975             if (dsp_fmt == DSP_DEC)
02976                printf("%8.li ", *((DWORD *) pdata));
02977             if (dsp_fmt == DSP_ASC)
02978                printf("%8.8lx ", *((DWORD *) pdata));
02979             if (dsp_fmt == DSP_HEX)
02980                printf("%8.8lx ", *((DWORD *) pdata));
02981             pdata++;
02982          }
02983       }
02984    }
02985 }
02986 
02987 /*------------------------------------------------------------------*/
02988 void ybos_bank_display(YBOS_BANK_HEADER * pybk, INT dsp_fmt)
02989 /********************************************************************\
02990 Routine: ybos_event_display
02991 Purpose: display on screen the YBOS data in YBOS bank mode.
02992 Input:
02993 YBOS_BANK_HEADER * pybk     pointer to the bank header
02994 INT     dsp_fmt             display format (DSP_DEC/HEX)
02995 Output:             
02996 none
02997 Function value:
02998 none
02999 \********************************************************************/
03000 {
03001    char bank_name[5], strbktype[32];
03002    DWORD length_type = 0;
03003    DWORD *pdata, *pendbk;
03004    INT i, j;
03005 
03006    j = 8;                       /* elements within line */
03007    i = 1;                       /* data counter */
03008 
03009    pdata = (DWORD *) (pybk + 1);
03010    memcpy(&bank_name[0], (char *) &pybk->name, 4);
03011    bank_name[4] = 0;
03012 
03013    if (pybk->type == D8_BKTYPE) {
03014       length_type = ((pybk->length - 1) >> 1);
03015       sprintf(strbktype, "double*8 (FMT machine dependent)");
03016    }
03017    if (pybk->type == F4_BKTYPE) {
03018       length_type = pybk->length - 1;
03019       strcpy(strbktype, "Real*4 (FMT machine dependent)");
03020    }
03021    if (pybk->type == I4_BKTYPE) {
03022       length_type = pybk->length - 1;
03023       strcpy(strbktype, "Integer*4");
03024    }
03025    if (pybk->type == I2_BKTYPE) {
03026       length_type = ((pybk->length - 1) << 1);
03027       strcpy(strbktype, "Integer*2");
03028    }
03029    if (pybk->type == I1_BKTYPE) {
03030       length_type = ((pybk->length - 1) << 2);
03031       strcpy(strbktype, "8 bit Bytes");
03032    }
03033    if (pybk->type == A1_BKTYPE) {
03034       length_type = ((pybk->length - 1) << 2);
03035       strcpy(strbktype, "8 bit ASCII");
03036    }
03037    printf("\nBank:%s Length: %li(I*1)/%li(I*4)/%li(Type) Type:%s",
03038           bank_name, ((pybk->length - 1) << 2), pybk->length - 1, length_type, strbktype);
03039    j = 16;
03040 
03041    pendbk = pdata + pybk->length - 1;
03042    while ((BYTE *) pdata < (BYTE *) pendbk) {
03043       switch (pybk->type) {
03044       case D8_BKTYPE:
03045          if (j > 7) {
03046             printf("\n%4i-> ", i);
03047             j = 0;
03048             i += 8;
03049          }
03050          printf("%15.5le  ", *((double *) pdata));
03051          pdata = (DWORD *) (((double *) pdata) + 1);
03052          j++;
03053          break;
03054       case F4_BKTYPE:
03055          if (j > 7) {
03056             printf("\n%4i-> ", i);
03057             j = 0;
03058             i += 8;
03059          }
03060          if ((dsp_fmt == DSP_DEC) || (dsp_fmt == DSP_UNK))
03061             printf("%8.3e ", *((float *) pdata));
03062          if (dsp_fmt == DSP_HEX)
03063             printf("0x%8.8lx ", *((DWORD *) pdata));
03064          pdata++;
03065          j++;
03066          break;
03067       case I4_BKTYPE:
03068          if (j > 7) {
03069             printf("\n%4i-> ", i);
03070             j = 0;
03071             i += 8;
03072          }
03073          if (dsp_fmt == DSP_DEC)
03074             printf("%8.1li ", *((DWORD *) pdata));
03075          if ((dsp_fmt == DSP_HEX) || (dsp_fmt == DSP_UNK))
03076             printf("0x%8.8lx ", *((DWORD *) pdata));
03077          pdata++;
03078          j++;
03079          break;
03080       case I2_BKTYPE:
03081          if (j > 7) {
03082             printf("\n%4i-> ", i);
03083             j = 0;
03084             i += 8;
03085          }
03086          if (dsp_fmt == DSP_DEC)
03087             printf("%5.1i ", *((WORD *) pdata));
03088          if ((dsp_fmt == DSP_HEX) || (dsp_fmt == DSP_UNK))
03089             printf("0x%4.4x ", *((WORD *) pdata));
03090          pdata = (DWORD *) (((WORD *) pdata) + 1);
03091          j++;
03092          break;
03093       case A1_BKTYPE:
03094          if (j > 15) {
03095             printf("\n%4i-> ", i);
03096             j = 0;
03097             i += 16;
03098          }
03099          if ((dsp_fmt == DSP_ASC) || (dsp_fmt == DSP_UNK))
03100             printf("%1.1s ", (char *) pdata);
03101          if (dsp_fmt == DSP_DEC)
03102             printf("%2.i ", *((BYTE *) pdata));
03103          if (dsp_fmt == DSP_HEX)
03104             printf("0x%2.2x ", *((BYTE *) pdata));
03105          pdata = (DWORD *) (((BYTE *) pdata) + 1);
03106          j++;
03107          break;
03108       case I1_BKTYPE:
03109          if (j > 7) {
03110             printf("\n%4i-> ", i);
03111             j = 0;
03112             i += 8;
03113          }
03114          if ((dsp_fmt == DSP_DEC) || (dsp_fmt == DSP_UNK))
03115             printf("%4.i ", *((BYTE *) pdata));
03116          if (dsp_fmt == DSP_HEX)
03117             printf("0x%2.2x ", *((BYTE *) pdata));
03118          pdata = (DWORD *) (((BYTE *) pdata) + 1);
03119          j++;
03120          break;
03121       default:
03122          printf("ybos_bak_display-E- Unknown bank type %li\n", pybk->type);
03123          break;
03124 
03125       }                         /* switch */
03126    }                            /* while next bank */
03127    printf("\n");
03128    return;
03129 }
03130 
03131 /*------------------------------------------------------------------*/
03132 void midas_bank_display(BANK * pbk, INT dsp_fmt)
03133 /******************************* *************************************\
03134 Routine: midas_bank_display
03135 Purpose: display on screen the pointed MIDAS bank data using MIDAS Bank structure.
03136 Input:
03137 BANK *  pbk            pointer to the BANK
03138 INT     dsp_fmt        display format (DSP_DEC/HEX)
03139 Output:
03140 none
03141 Function value:
03142 none
03143 \********************************************************************/
03144 {
03145    char bank_name[5], strbktype[32];
03146    char *pdata, *pendbk;
03147    DWORD length_type = 0, lrl;
03148    INT type, i, j;
03149 
03150    lrl = pbk->data_size;        /* in bytes */
03151    type = pbk->type & 0xff;
03152    bank_name[4] = 0;
03153    memcpy(bank_name, (char *) (pbk->name), 4);
03154    pdata = (char *) (pbk + 1);
03155 
03156    j = 64;                      /* elements within line */
03157    i = 1;                       /* data counter */
03158    strcpy(strbktype, "Unknown format");
03159    if (type == TID_DOUBLE) {
03160       length_type = sizeof(double);
03161       strcpy(strbktype, "double*8");
03162    }
03163    if (type == TID_FLOAT) {
03164       length_type = sizeof(float);
03165       strcpy(strbktype, "Real*4 (FMT machine dependent)");
03166    }
03167    if (type == TID_DWORD) {
03168       length_type = sizeof(DWORD);
03169       strcpy(strbktype, "Unsigned Integer*4");
03170    }
03171    if (type == TID_INT) {
03172       length_type = sizeof(INT);
03173       strcpy(strbktype, "Signed Integer*4");
03174    }
03175    if (type == TID_WORD) {
03176       length_type = sizeof(WORD);
03177       strcpy(strbktype, "Unsigned Integer*2");
03178    }
03179    if (type == TID_SHORT) {
03180       length_type = sizeof(short);
03181       strcpy(strbktype, "Signed Integer*2");
03182    }
03183    if (type == TID_BYTE) {
03184       length_type = sizeof(BYTE);
03185       strcpy(strbktype, "Unsigned Bytes");
03186    }
03187    if (type == TID_SBYTE) {
03188       length_type = sizeof(BYTE);
03189       strcpy(strbktype, "Signed Bytes");
03190    }
03191    if (type == TID_BOOL) {
03192       length_type = sizeof(DWORD);
03193       strcpy(strbktype, "Boolean");
03194    }
03195    if (type == TID_CHAR) {
03196       length_type = sizeof(char);
03197       strcpy(strbktype, "8 bit ASCII");
03198    }
03199    if (type == TID_STRUCT) {
03200       length_type = sizeof(char);
03201       strcpy(strbktype, "STRUCT (not supported->8 bits)");
03202    }
03203 
03204    printf("\nBank:%s Length: %li(I*1)/%li(I*4)/%li(Type) Type:%s",
03205           bank_name, lrl, lrl >> 2, lrl / length_type, strbktype);
03206 
03207    pendbk = pdata + lrl;
03208    while (pdata < pendbk) {
03209       switch (type) {
03210       case TID_DOUBLE:
03211          if (j > 3) {
03212             printf("\n%4i-> ", i);
03213             j = 0;
03214             i += 4;
03215          }
03216          printf("%15.5le    ", *((double *) pdata));
03217          pdata = (char *) (((double *) pdata) + 1);
03218          j++;
03219          break;
03220       case TID_FLOAT:
03221          if (j > 7) {
03222             printf("\n%4i-> ", i);
03223             j = 0;
03224             i += 8;
03225          }
03226          if ((dsp_fmt == DSP_DEC) || (dsp_fmt == DSP_UNK))
03227             printf("%8.3e ", *((float *) pdata));
03228          if (dsp_fmt == DSP_HEX)
03229             printf("0x%8.8lx ", *((DWORD *) pdata));
03230          pdata = (char *) (((DWORD *) pdata) + 1);
03231          j++;
03232          break;
03233       case TID_DWORD:
03234          if (j > 7) {
03235             printf("\n%4i-> ", i);
03236             j = 0;
03237             i += 8;
03238          }
03239          if (dsp_fmt == DSP_DEC)
03240             printf("%8.1li ", *((DWORD *) pdata));
03241          if ((dsp_fmt == DSP_HEX) || (dsp_fmt == DSP_UNK))
03242             printf("0x%8.8lx ", *((DWORD *) pdata));
03243          pdata = (char *) (((DWORD *) pdata) + 1);
03244          j++;
03245          break;
03246       case TID_INT:
03247          if (j > 7) {
03248             printf("\n%4i-> ", i);
03249             j = 0;
03250             i += 8;
03251          }
03252          if ((dsp_fmt == DSP_DEC) || (dsp_fmt == DSP_UNK))
03253             printf("%8.1li ", *((DWORD *) pdata));
03254          if (dsp_fmt == DSP_HEX)
03255             printf("0x%8.8lx ", *((DWORD *) pdata));
03256          pdata = (char *) (((DWORD *) pdata) + 1);
03257          j++;
03258          break;
03259       case TID_WORD:
03260          if (j > 7) {
03261             printf("\n%4i-> ", i);
03262             j = 0;
03263             i += 8;
03264          }
03265          if (dsp_fmt == DSP_DEC)
03266             printf("%5.1i ", *((WORD *) pdata));
03267          if ((dsp_fmt == DSP_HEX) || (dsp_fmt == DSP_UNK))
03268             printf("0x%4.4x ", *((WORD *) pdata));
03269          pdata = (char *) (((WORD *) pdata) + 1);
03270          j++;
03271          break;
03272       case TID_SHORT:
03273          if (j > 7) {
03274             printf("\n%4i-> ", i);
03275             j = 0;
03276             i += 8;
03277          }
03278          if ((dsp_fmt == DSP_DEC) || (dsp_fmt == DSP_UNK))
03279             printf("%5.1i ", *((short *) pdata));
03280          if (dsp_fmt == DSP_HEX)
03281             printf("0x%4.4x ", *((short *) pdata));
03282          pdata = (char *) (((short *) pdata) + 1);
03283          j++;
03284          break;
03285       case TID_BYTE:
03286       case TID_STRUCT:
03287          if (j > 15) {
03288             printf("\n%4i-> ", i);
03289             j = 0;
03290             i += 16;
03291          }
03292          if (dsp_fmt == DSP_DEC)
03293             printf("%4.i ", *((BYTE *) pdata));
03294          if ((dsp_fmt == DSP_HEX) || (dsp_fmt == DSP_UNK))
03295             printf("0x%2.2x ", *((BYTE *) pdata));
03296          pdata++;
03297          j++;
03298          break;
03299       case TID_SBYTE:
03300          if (j > 15) {
03301             printf("\n%4i-> ", i);
03302             j = 0;
03303             i += 16;
03304          }
03305          if ((dsp_fmt == DSP_DEC) || (dsp_fmt == DSP_UNK))
03306             printf("%4.i ", *((BYTE *) pdata));
03307          if (dsp_fmt == DSP_HEX)
03308             printf("0x%2.2x ", *((BYTE *) pdata));
03309          pdata++;
03310          j++;
03311          break;
03312       case TID_BOOL:
03313          if (j > 15) {
03314             printf("\n%4i-> ", i);
03315             j = 0;
03316             i += 16;
03317          }
03318          (*((BOOL *) pdata) != 0) ? printf("Y ") : printf("N ");
03319          pdata = (char *) (((DWORD *) pdata) + 1);
03320          j++;
03321          break;
03322       case TID_CHAR:
03323          if (j > 15) {
03324             printf("\n%4i-> ", i);
03325             j = 0;
03326             i += 16;
03327          }
03328          if (dsp_fmt == DSP_DEC)
03329             printf("%3.i ", *((BYTE *) pdata));
03330          if ((dsp_fmt == DSP_ASC) || (dsp_fmt == DSP_UNK))
03331             printf("%1.1s ", (char *) pdata);
03332          if (dsp_fmt == DSP_HEX)
03333             printf("0x%2.2x ", *((BYTE *) pdata));
03334          pdata++;
03335          j++;
03336          break;
03337       default:
03338          printf("bank type not supported (%d)\n", type);
03339          return;
03340          break;
03341       }
03342    }                            /* end of bank */
03343    printf("\n");
03344    return;
03345 }
03346 
03347 /*------------------------------------------------------------------*/
03348 void midas_bank_display32(BANK32 * pbk, INT dsp_fmt)
03349 /********************************************************************\
03350 Routine: midas_bank_display32
03351 Purpose: display on screen the pointed MIDAS bank data using MIDAS Bank structure.
03352 for 32bit length banks
03353 Input:
03354 BANK32 *  pbk            pointer to the BANK
03355 INT     dsp_fmt        display format (DSP_DEC/HEX)
03356 Output:
03357 none
03358 Function value:
03359 none
03360 \********************************************************************/
03361 {
03362    char bank_name[5], strbktype[32];
03363    char *pdata, *pendbk;
03364    DWORD length_type = 0, lrl;
03365    INT type, i, j;
03366 
03367    lrl = pbk->data_size;        /* in bytes */
03368    type = pbk->type & 0xff;
03369    bank_name[4] = 0;
03370    memcpy(bank_name, (char *) (pbk->name), 4);
03371    pdata = (char *) (pbk + 1);
03372 
03373    j = 64;                      /* elements within line */
03374    i = 1;                       /* data counter */
03375    strcpy(strbktype, "Unknown format");
03376    if (type == TID_DOUBLE) {
03377       length_type = sizeof(double);
03378       strcpy(strbktype, "double*8");
03379    }
03380    if (type == TID_FLOAT) {
03381       length_type = sizeof(float);
03382       strcpy(strbktype, "Real*4 (FMT machine dependent)");
03383    }
03384    if (type == TID_DWORD) {
03385       length_type = sizeof(DWORD);
03386       strcpy(strbktype, "Unsigned Integer*4");
03387    }
03388    if (type == TID_INT) {
03389       length_type = sizeof(INT);
03390       strcpy(strbktype, "Signed Integer*4");
03391    }
03392    if (type == TID_WORD) {
03393       length_type = sizeof(WORD);
03394       strcpy(strbktype, "Unsigned Integer*2");
03395    }
03396    if (type == TID_SHORT) {
03397       length_type = sizeof(short);
03398       strcpy(strbktype, "Signed Integer*2");
03399    }
03400    if (type == TID_BYTE) {
03401       length_type = sizeof(BYTE);
03402       strcpy(strbktype, "8 bit Bytes");
03403    }
03404    if (type == TID_SBYTE) {
03405       length_type = sizeof(BYTE);
03406       strcpy(strbktype, "Signed Bytes");
03407    }
03408    if (type == TID_BOOL) {
03409       length_type = sizeof(DWORD);
03410       strcpy(strbktype, "Boolean");
03411    }
03412    if (type == TID_CHAR) {
03413       length_type = sizeof(char);
03414       strcpy(strbktype, "8 bit ASCII");
03415    }
03416    if (type == TID_STRUCT) {
03417       length_type = sizeof(char);
03418       strcpy(strbktype, "STRUCT (not supported->8 bits)");
03419    }
03420    printf("\nBank:%s Length: %li(I*1)/%li(I*4)/%li(Type) Type:%s",
03421           bank_name, lrl, lrl >> 2, lrl / length_type, strbktype);
03422 
03423    pendbk = pdata + lrl;
03424 
03425    while (pdata < pendbk) {
03426       switch (type) {
03427       case TID_DOUBLE:
03428          if (j > 3) {
03429             printf("\n%4i-> ", i);
03430             j = 0;
03431             i += 4;
03432          }
03433          printf("%15.5le    ", *((double *) pdata));
03434          pdata = (char *) (((double *) pdata) + 1);
03435          j++;
03436          break;
03437       case TID_FLOAT:
03438          if (j > 7) {
03439             printf("\n%4i-> ", i);
03440             j = 0;
03441             i += 8;
03442          }
03443          if ((dsp_fmt == DSP_DEC) || (dsp_fmt == DSP_UNK))
03444             printf("%8.3e ", *((float *) pdata));
03445          if (dsp_fmt == DSP_HEX)
03446             printf("0x%8.8lx ", *((DWORD *) pdata));
03447          pdata = (char *) (((DWORD *) pdata) + 1);
03448          j++;
03449          break;
03450       case TID_DWORD:
03451          if (j > 7) {
03452             printf("\n%4i-> ", i);
03453             j = 0;
03454             i += 8;
03455          }
03456          if (dsp_fmt == DSP_DEC)
03457             printf("%8.1li ", *((DWORD *) pdata));
03458          if ((dsp_fmt == DSP_HEX) || (dsp_fmt == DSP_UNK))
03459             printf("0x%8.8lx ", *((DWORD *) pdata));
03460          pdata = (char *) (((DWORD *) pdata) + 1);
03461          j++;
03462          break;
03463       case TID_INT:
03464          if (j > 7) {
03465             printf("\n%4i-> ", i);
03466             j = 0;
03467             i += 8;
03468          }
03469          if ((dsp_fmt == DSP_DEC) || (dsp_fmt == DSP_UNK))
03470             printf("%8.1li ", *((DWORD *) pdata));
03471          if (dsp_fmt == DSP_HEX)
03472             printf("0x%8.8lx ", *((DWORD *) pdata));
03473          pdata = (char *) (((DWORD *) pdata) + 1);
03474          j++;
03475          break;
03476       case TID_WORD:
03477          if (j > 7) {
03478             printf("\n%4i-> ", i);
03479             j = 0;
03480             i += 8;
03481          }
03482          if (dsp_fmt == DSP_DEC)
03483             printf("%5.1i ", *((WORD *) pdata));
03484          if ((dsp_fmt == DSP_HEX) || (dsp_fmt == DSP_UNK))
03485             printf("0x%4.4x ", *((WORD *) pdata));
03486          pdata = (char *) (((WORD *) pdata) + 1);
03487          j++;
03488          break;
03489       case TID_SHORT:
03490          if (j > 7) {
03491             printf("\n%4i-> ", i);
03492             j = 0;
03493             i += 8;
03494          }
03495          if ((dsp_fmt == DSP_DEC) || (dsp_fmt == DSP_UNK))
03496             printf("%5.1i ", *((short *) pdata));
03497          if (dsp_fmt == DSP_HEX)
03498             printf("0x%4.4x ", *((short *) pdata));
03499          pdata = (char *) (((short *) pdata) + 1);
03500          j++;
03501          break;
03502       case TID_BYTE:
03503       case TID_STRUCT:
03504          if (j > 15) {
03505             printf("\n%4i-> ", i);
03506             j = 0;
03507             i += 16;
03508          }
03509          if (dsp_fmt == DSP_DEC)
03510             printf("%4.i ", *((BYTE *) pdata));
03511          if ((dsp_fmt == DSP_HEX) || (dsp_fmt == DSP_UNK))
03512             printf("0x%2.2x ", *((BYTE *) pdata));
03513          pdata++;
03514          j++;
03515          break;
03516       case TID_SBYTE:
03517          if (j > 15) {
03518             printf("\n%4i-> ", i);
03519             j = 0;
03520             i += 16;
03521          }
03522          if ((dsp_fmt == DSP_DEC) || (dsp_fmt == DSP_UNK))
03523             printf("%4.i ", *((BYTE *) pdata));
03524          if (dsp_fmt == DSP_HEX)
03525             printf("0x%2.2x ", *((BYTE *) pdata));
03526          pdata++;
03527          j++;
03528          break;
03529       case TID_BOOL:
03530          if (j > 15) {
03531             printf("\n%4i-> ", i);
03532             j = 0;
03533             i += 16;
03534          }
03535          (*((BOOL *) pdata) != 0) ? printf("Y ") : printf("N ");
03536          pdata = (char *) (((DWORD *) pdata) + 1);
03537          j++;
03538          break;
03539       case TID_CHAR:
03540          if (j > 15) {
03541             printf("\n%4i-> ", i);
03542             j = 0;
03543             i += 16;
03544          }
03545          if (dsp_fmt == DSP_DEC)
03546             printf("%3.i ", *((BYTE *) pdata));
03547          if (dsp_fmt == DSP_ASC || (dsp_fmt == DSP_UNK))
03548             printf("%1.1s ", (char *) pdata);
03549          if (dsp_fmt == DSP_HEX)
03550             printf("0x%2.2x ", *((BYTE *) pdata));
03551          pdata++;
03552          j++;
03553          break;
03554       default:
03555          printf("bank type not supported (%d)\n", type);
03556          return;
03557          break;
03558       }
03559    }                            /* end of bank */
03560    printf("\n");
03561    return;
03562 }
03563 
03564 /*-- GENERAL file fragmentation and recovery -----Section d)--------*/
03565 /*-- GENERAL file fragmentation and recovery -----------------------*/
03566 /*-- GENERAL file fragmentation and recovery -----------------------*/
03567 /*-- GENERAL file fragmentation and recovery -----------------------*/
03568 /*------------------------------------------------------------------*/
03569 INT yb_file_recompose(void *pevt, INT format, char *svpath, INT file_mode)
03570 /********************************************************************\
03571 Routine: external file_recompose
03572 Purpose: Receive event which are expected to be file oriented with
03573 YM_xFILE header.
03574 Input:
03575 char * pevt           pointer to a YBOS event (->LRL).
03576 char * svpath         path where to save file
03577 INT    file_mode      NO_RUN : save file under original name
03578 ADD_RUN: cat run number at end of file name
03579 Output:
03580 none
03581 Function value:
03582 YB_SUCCESS         OP successfull
03583 YB_INCOMPLETE      file compose channels still open
03584 YB_COMPLETE        All file compose channels closed or complete
03585 status             -x error of inner call
03586 \********************************************************************/
03587 {
03588    YM_CFILE *pmyfch;
03589    int slot, status;
03590 
03591    if (file_mode == YB_NO_RECOVER)
03592       return YB_SUCCESS;
03593 
03594    if (format == FORMAT_YBOS) {
03595       if ((status = ybk_locate((DWORD *) pevt, "CFIL", &pmyfch)) <= 0)
03596          return (status);
03597    } else if (format == FORMAT_MIDAS) {
03598       if ((((EVENT_HEADER *) pevt)->event_id == EVENTID_BOR) ||
03599           (((EVENT_HEADER *) pevt)->event_id == EVENTID_EOR) ||
03600           (((EVENT_HEADER *) pevt)->event_id == EVENTID_MESSAGE))
03601          return YB_BANK_NOT_FOUND;
03602 
03603       pevt = (EVENT_HEADER *) pevt + 1;
03604       if ((status = bk_locate(pevt, "CFIL", &pmyfch)) <= 0)
03605          return (status);
03606    }
03607 
03608    printf("%i - %i - %i - %i - %i -%i -%i \n", pmyfch->file_ID,
03609           pmyfch->size, pmyfch->fragment_size, pmyfch->total_fragment,
03610           pmyfch->current_fragment, pmyfch->current_read_byte, pmyfch->run_number);
03611 
03612    /* check if file is in progress */
03613    for (slot = 0; slot < MAX_YM_FILE; slot++) {
03614       if ((ymfile[slot].fHandle != 0)
03615           && (pmyfch->file_ID == ymfile[slot].file_ID)) {
03616          /* Yep file in progress for that file_ID */
03617          if ((status = yb_ymfile_update(slot, format, pevt)) != YB_SUCCESS) {
03618             printf("yb_ymfile_update() failed\n");
03619             return status;
03620          }
03621          goto check;
03622       }
03623       /* next slot */
03624    }
03625    /* current fragment not registered => new file */
03626    /* open file, get slot back */
03627    if ((status = yb_ymfile_open(&slot, format, pevt, svpath, file_mode)) != YB_SUCCESS) {
03628       printf("yb_ymfile_open() failed\n");
03629       return status;
03630    }
03631    /* update file */
03632    if ((status = yb_ymfile_update(slot, format, pevt)) != YB_SUCCESS) {
03633       printf("yb_ymfile_update() failed\n");
03634       return status;
03635    }
03636 
03637  check:
03638    /* for completion of recovery on ALL files */
03639    for (slot = 0; slot < MAX_YM_FILE; slot++) {
03640       if (ymfile[slot].fHandle != 0) {
03641          /* Yes still some file composition in progress */
03642          return YB_INCOMPLETE;
03643       }
03644       /* next slot */
03645    }
03646    return YB_COMPLETE;
03647 }
03648 
03649 /*------------------------------------------------------------------*/
03650 INT yb_ymfile_open(int *slot, int fmt, void *pevt, char *svpath, INT file_mode)
03651 /********************************************************************\
03652 Routine: yb_ymfile_open
03653 Purpose: Prepare channel for receiving event of YM_FILE type.
03654 Input:
03655 void * pevt           pointer to the data portion of the event
03656 char * svpath         path where to save file
03657 INT    file_mode      NO_RUN : save file under original name
03658 ADD_RUN: cat run number at end of file name
03659 Output:
03660 INT  * slot           index of the opened channel
03661 Function value:
03662 YB_SUCCESS          Successful completion
03663 YB_FAIL_OPEN        cannot create output file
03664 YB_NOMORE_SLOT      no more slot for starting dump
03665 \********************************************************************/
03666 {
03667    YM_CFILE *pmyfch;
03668    YM_PFILE *pmyfph;
03669    char *pfilename;
03670    char srun[16], sslot[3];
03671    int i, status;
03672 
03673    /* initialize invalid slot */
03674    *slot = -1;
03675 
03676    if (fmt == FORMAT_YBOS) {
03677       if ((status = ybk_locate((DWORD *) pevt, "CFIL", &pmyfch)) <= 0)
03678          return (status);
03679       if ((status = ybk_locate((DWORD *) pevt, "PFIL", &pmyfph)) <= 0)
03680          return (status);
03681    } else if (fmt == FORMAT_MIDAS) {
03682       if ((status = bk_locate(pevt, "CFIL", &pmyfch)) <= 0)
03683          return (status);
03684       if ((status = bk_locate(pevt, "PFIL", &pmyfph)) <= 0)
03685          return (status);
03686    } else
03687       return -2;
03688    /* find free slot */
03689    for (i = 0; i < MAX_YM_FILE; i++)
03690       if (ymfile[i].fHandle == 0)
03691          break;
03692    if (i < MAX_YM_FILE) {
03693       /* copy necessary file header info */
03694       ymfile[i].file_ID = pmyfch->file_ID;
03695       strcpy(ymfile[i].path, pmyfph->path);
03696 
03697       /* extract file name */
03698       pfilename = pmyfph->path;
03699       if (strrchr(pmyfph->path, '/') > pfilename)
03700          pfilename = strrchr(pmyfph->path, '/');
03701       if (strrchr(pmyfph->path, '\\') > pfilename)
03702          pfilename = strrchr(pmyfph->path, '\\');
03703       if (strrchr(pmyfph->path, ':') > pfilename)
03704          pfilename = strrchr(pmyfph->path, ':');
03705       if (*pfilename != pmyfph->path[0])
03706          pfilename++;
03707 
03708       /* add path name */
03709       if (svpath[0] != 0) {
03710          ymfile[i].path[0] = 0;
03711          strncat(ymfile[i].path, svpath, strlen(svpath));
03712          if (ymfile[i].path[strlen(ymfile[i].path) - 1] != DIR_SEPARATOR)
03713             strcat(ymfile[i].path, DIR_SEPARATOR_STR);
03714          /* append the file name */
03715          strcat(ymfile[i].path, pfilename);
03716       }
03717       if (file_mode == YB_ADD_RUN) {    /* append run number */
03718          strcat(ymfile[i].path, ".");
03719          sprintf(srun, "Run%4.4i", pmyfch->run_number);
03720          strncat(ymfile[i].path, srun, strlen(srun));
03721       }
03722       /* differentiate the possible file dumps 
03723          as the path is unique */
03724       if (i > 0) {
03725          sprintf(sslot, ".%03i", i);
03726          strcat(ymfile[i].path, sslot);
03727       }
03728 
03729       /* open device */
03730       if ((ymfile[i].fHandle =
03731            open(ymfile[i].path, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE, 0644)) == -1) {
03732          ymfile[i].fHandle = 0;
03733          printf("File %s cannot be created\n", ymfile[i].path);
03734          return (SS_FILE_ERROR);
03735       }
03736    } else {
03737       /* no more slot */
03738       printf("No more slot for file %s\n", pmyfph->path);
03739       return YB_NOMORE_SLOT;
03740    }
03741 
03742    ymfile[i].current_read_byte = 0;
03743    ymfile[i].current_fragment = 0;
03744    *slot = i;
03745    return YB_SUCCESS;
03746 }
03747 
03748 /*------------------------------------------------------------------*/
03749 INT yb_ymfile_update(int slot, int fmt, void *pevt)
03750 /********************************************************************\
03751 Routine: yb_ymfile_update
03752 Purpose: dump Midas/Ybos event to file for YBOS file oriented event type.
03753 Input:
03754 char * pevt           pointer to the data portion of the event.
03755 Output:
03756 INT  slot             valid index of the opened channel.
03757 Function value:
03758 YB_SUCCESS         Successful completion
03759 -1                     error
03760 \********************************************************************/
03761 {
03762    YM_CFILE *pmyfch;
03763    char *pmyfd;
03764    int status;
03765    int nwrite;
03766 
03767    if (fmt == FORMAT_YBOS) {
03768       if ((status = ybk_locate((DWORD *) pevt, "CFIL", &pmyfch)) <= 0)
03769          return (status);
03770       if ((status = ybk_locate((DWORD *) pevt, "DFIL", &pmyfd)) <= 0)
03771          return (status);
03772 
03773       /* check sequence order */
03774       if (ymfile[slot].current_fragment + 1 != pmyfch->current_fragment) {
03775          printf("Out of sequence %i / %i\n", ymfile[slot].current_fragment,
03776                 pmyfch->current_fragment);
03777       }
03778       /* dump fragment to file */
03779       nwrite = write(ymfile[slot].fHandle, pmyfd, pmyfch->fragment_size);
03780 
03781       /* update current file record */
03782       ymfile[slot].current_read_byte += nwrite;
03783       ymfile[slot].current_fragment++;
03784       /* check if file has to be closed */
03785       if (ymfile[slot].current_fragment == pmyfch->total_fragment) {
03786          /* file complete */
03787          close(ymfile[slot].fHandle);
03788          printf("File %s (%i) completed\n", ymfile[slot].path,
03789                 ymfile[slot].current_read_byte);
03790          /* cleanup slot */
03791          ymfile[slot].fHandle = 0;
03792          return YB_SUCCESS;
03793       } /* close file */
03794       else {
03795          /* fragment retrieved wait next one */
03796          return YB_SUCCESS;
03797       }
03798    } else if (fmt == FORMAT_MIDAS) {
03799       if ((status = bk_locate(pevt, "CFIL", &pmyfch)) <= 0)
03800          return (status);
03801       if ((status = bk_locate(pevt, "DFIL", &pmyfd)) <= 0)
03802          return (status);
03803 
03804       /* check sequence order */
03805       if (ymfile[slot].current_fragment + 1 != pmyfch->current_fragment) {
03806          printf("Out of sequence %i / %i\n", ymfile[slot].current_fragment,
03807                 pmyfch->current_fragment);
03808       }
03809       /* dump fragment to file */
03810       nwrite = write(ymfile[slot].fHandle, pmyfd, pmyfch->fragment_size);
03811 
03812       /* update current file record */
03813       ymfile[slot].current_read_byte += nwrite;
03814       ymfile[slot].current_fragment++;
03815       /* check if file has to be closed */
03816       if (ymfile[slot].current_fragment == pmyfch->total_fragment) {
03817          /* file complete */
03818          close(ymfile[slot].fHandle);
03819          printf("File %s (%i) completed\n", ymfile[slot].path,
03820                 ymfile[slot].current_read_byte);
03821          /* cleanup slot */
03822          ymfile[slot].fHandle = 0;
03823          return YB_SUCCESS;
03824       } /* close file */
03825       else {
03826          /* fragment retrieved wait next one */
03827          return YB_SUCCESS;
03828       }
03829    } else
03830       return YB_UNKNOWN_FORMAT;
03831 }
03832 #endif                          /* OS_VXWORKS Frontend */
03833 
03834 /*------------------------------------------------------------------*/
03835 /*------------------------------------------------------------------*/
03836 /*------------------------------------------------------------------*/
03837 /*--END of YBOS.C---------------------------------------------------*/
03838 /*------------------------------------------------------------------*/
03839 /*------------------------------------------------------------------*/
03840 /*------------------------------------------------------------------*/
03841 
03842 
03843 /**dox***************************************************************/
03844 #endif                          /* DOXYGEN_SHOULD_SKIP_THIS */
03845 
03846 /**dox***************************************************************/
03847 /** @} */ /* end of ybosbankc */
03848 
03849 /**dox***************************************************************/
03850 /** @} */ /* end of ybosincludecode */

Midas DOC Version 1.9.3 ---- PSI Stefan Ritt ----
Contributions: Pierre-Andre Amaudruz - Suzannah Daviel - Doxygen - Peter Green - Greg Hackman - Gertjan Hofman - Paul Knowles - Rudi Meier - Glenn Moloney - Dave Morris - John M O'Donnell - Konstantin Olchanski - Renee Poutissou - Andreas Suter - Jan M.Wouters - Piotr Adam Zolnierczuk