Class Reference for E1039 Core & Analysis Software
evio.c
Go to the documentation of this file.
1 /*-----------------------------------------------------------------------------
2  * Copyright (c) 1991,1992 Southeastern Universities Research Association,
3  * Continuous Electron Beam Accelerator Facility
4  *
5  * This software was developed under a United States Government license
6  * described in the NOTICE file included as part of this distribution.
7  *
8  * CEBAF Data Acquisition Group, 12000 Jefferson Ave., Newport News, VA 23606
9  * Email: coda@cebaf.gov Tel: (804) 249-7101 Fax: (804) 249-7363
10  *-----------------------------------------------------------------------------
11  *
12  * Description:
13  * Event I/O routines
14  *
15  * Author: Chip Watson, CEBAF Data Acquisition Group
16  * Modified: Stephen A. Wood, TJNAF Hall C
17  * Works on ALPHA 64 bit machines if BIT64 is defined
18  * Will read input from standard input if filename is "-"
19  * If input filename is "|command" will take data from standard output
20  * of command.
21  * If input file is compressed and unconpressible with gunzip, it will
22  * decompress the data on the fly.
23  *
24  * Revision History:
25  * $Log: evio.c,v $
26  * Revision 1.3 1999/11/04 20:30:48 saw
27  * Add code to write coda output to stdout or pipes
28  *
29  * Revision 1.2 1998/12/01 13:54:12 saw
30  * (saw) Alpha 64 bit fixes, input from std input, pipes and compressed
31  * files
32  *
33  * Revision 1.1 1996/12/19 14:05:02 saw
34  * Initial revision
35  *
36  * Revision 1.5 1994/08/15 15:45:09 chen
37  * add evnum to EVFILE structure. Keep event number when call evWrite
38  *
39  * Revision 1.4 1994/08/12 17:14:55 chen
40  * check event type explicitly
41  *
42  * Revision 1.3 1994/06/17 16:11:12 chen
43  * fix a bug when there is a single special event in the last block
44  *
45  * Revision 1.2 1994/05/12 15:38:37 chen
46  * In case a wrong data format, close file and free memory
47  *
48  * Revision 1.1 1994/04/11 13:07:06 chen
49  * Initial revision
50  *
51 * Revision 1.6 1993/11/16 20:57:27 chen
52 * stronger type casting for swapped_memecpy
53 *
54 * Revision 1.5 1993/11/09 18:21:58 chen
55 * fix a bug
56 *
57 * Revision 1.4 1993/11/09 18:16:49 chen
58 * add binary search routines
59 *
60 * Revision 1.3 1993/11/03 16:40:55 chen
61 * cosmatic change
62 *
63 * Revision 1.2 1993/11/03 16:39:39 chen
64 * add bytpe_swapped flag to EVFILE struct
65 *
66  *
67  *
68  *
69  * Routines
70  * --------
71  *
72  * evOpen(char *filename,char *flags,int *descriptor)
73  * evWrite(int descriptor,int *data,int datalen)
74  * evRead(int descriptor,int *data,int *datalen)
75  * evClose(int descriptor)
76  * evIoctl(int descriptor,char *request, void *argp)
77  *
78  * Modifications
79  * -------------
80  * 17-dec-91 cw started coding streams version with local buffers
81  */
82 #include <stdio.h>
83 #include <stdlib.h>
84 #include <string.h>
85 #include <errno.h>
86 #define PMODE 0644
87 #include "evfile_msg.h"
88 #include "evio.h"
89 
90 typedef struct evfilestruct {
91  FILE *file;
92  int *buf;
93  int *next;
94  int left;
95  int blksiz;
96  int blknum;
97  int rw;
98  int magic;
99  int evnum; /* last events with evnum so far */
100  int byte_swapped;
102 
103 typedef struct evBinarySearch{
104  int sbk;
105  int ebk;
106  int found_bk;
107  int found_evn;
108  int last_evn;
110 
111 #define EVBLOCKSIZE 8192
112 #define EV_READ 0
113 #define EV_WRITE 1
114 #define EV_PIPE 2
115 #define EV_PIPEWRITE 3
116 #define EV_VERSION 1
117 #define EV_MAGIC 0xc0da0100
118 #define EV_HDSIZ 8
119 
120 
121 #define EV_HD_BLKSIZ 0 /* size of block in longwords */
122 #define EV_HD_BLKNUM 1 /* number, starting at 0 */
123 #define EV_HD_HDSIZ 2 /* size of header in longwords (=8) */
124 #define EV_HD_START 3 /* first start of event in this block */
125 #define EV_HD_USED 4 /* number of words used in block (<= BLKSIZ) */
126 #define EV_HD_VER 5 /* version of file format (=1) */
127 #define EV_HD_RESVD 6 /* (reserved) */
128 #define EV_HD_MAGIC 7 /* magic number for error detection */
129 
130 #define evGetStructure() (EVFILE *)malloc(sizeof(EVFILE))
131 
132 static int findLastEventWithinBlock(EVFILE *);
133 static int copySingleEvent(EVFILE *, int *, int, int);
134 static int evSearchWithinBlock(EVFILE *, EVBSEARCH *, int *, int, int *, int, int *);
135 static void evFindEventBlockNum(EVFILE *, EVBSEARCH *, int *);
136 static int evGetEventNumber(EVFILE *, int);
137 static int evGetEventType(EVFILE *);
138 static int isRealEventsInsideBlock(EVFILE *, int, int);
139 static int physicsEventsInsideBlock(EVFILE *);
140 
141 extern int int_swap_byte();
142 extern void onmemory_swap();
143 extern int swapped_fread();
144 extern void swapped_intcpy();
145 extern void swapped_memcpy();
146 
147 #if defined(__osf__) && defined(__alpha)
148 #define BIT64
149 #endif
150 
151 #ifdef BIT64
152 #define MAXHANDLES 10
153 EVFILE *handle_list[10]={0,0,0,0,0,0,0,0,0,0};
154 #endif
155 
156 #ifdef AbsoftUNIXFortran
157 int evopen
158 #else
160 #endif
161 (char *filename,char *flags,int *handle,int fnlen,int flen)
162 {
163  char *fn, *fl;
164  int status;
165  fn = (char *) malloc(fnlen+1);
166  strncpy(fn,filename,fnlen);
167  fn[fnlen] = 0; /* insure filename is null terminated */
168  fl = (char *) malloc(flen+1);
169  strncpy(fl,flags,flen);
170  fl[flen] = 0; /* insure flags is null terminated */
171  status = evOpen(fn,fl,handle);
172  free(fn);
173  free(fl);
174  return(status);
175 }
176 
177 static char *kill_trailing(char *s, char t)
178 {
179  char *e;
180  e = s + strlen(s);
181  if (e>s) { /* Need this to handle NULL string.*/
182  while (e>s && *--e==t); /* Don't follow t's past beginning. */
183  e[*e==t?0:1] = '\0'; /* Handle s[0]=t correctly. */
184  }
185  return s;
186 }
187 int evOpen(char *fname,char *flags,int *handle)
188 {
189 #ifdef BIT64
190  int ihandle;
191 #endif
192  EVFILE *a;
193  char *cp;
194  int header[EV_HDSIZ];
195  int i;
196  int temp,blk_size;
197  char *filename;
198 
199  filename = malloc(strlen(fname)+1);
200  strcpy(filename,fname);
201  a = evGetStructure(); /* allocate control structure or quit */
202  if (!a) {
203  free(filename);
204  return(S_EVFILE_ALLOCFAIL);
205  }
206  while (*filename==' ') filename++; /* remove leading spaces */
207  /* But don't fuck with any other spaces except for the trailing ones */
208 #if 0
209  for (cp=filename;*cp!=NULL;cp++) {
210  if ((*cp==' ') || !(isprint(*cp))) *cp='\0';
211  }
212 #else
213  kill_trailing(filename,' ');
214 #endif
215  char c;
216  c = *flags;
217  switch (c)
218  /*case NULL:*/case 'r': case 'R': {
219  a->rw = EV_READ;
220  if(strcmp(filename,"-")==0) {
221  a->file = stdin;
222  } else if(filename[0] == '|') {
223  a->file = popen(filename+1,"r");
224  a->rw = EV_PIPE; /* Make sure we know to use pclose */
225  } else {
226  a->file = fopen(filename,"r");
227  if(a->file) {
228  int compressed;
229  char bytes[2];
230  fread(bytes,2,1,a->file); /* Check magic bytes for compressions */
231  if(bytes[0]=='\037' && (bytes[1]=='\213' || bytes[1]=='\235')) {
232  char *pipe_command;
233  fclose(a->file);
234  pipe_command = (char *)malloc(strlen(filename)+strlen("gunzip<")+1);
235  strcpy(pipe_command,"gunzip<");
236  strcat(pipe_command,filename);
237  a->file = popen(pipe_command,"r");
238  free(pipe_command);
239  a->rw = EV_PIPE;
240  } else {
241  fclose(a->file);
242  a->file = fopen(filename,"r");
243  }
244  }
245  }
246  if (a->file) {
247  fread(header,sizeof(header),1,a->file); /* update: check nbytes return */
248  if (header[EV_HD_MAGIC] != EV_MAGIC) {
249  temp = int_swap_byte(header[EV_HD_MAGIC]);
250  if(temp == EV_MAGIC)
251  a->byte_swapped = 1;
252  else{ /* close file and free memory */
253  fclose(a->file);
254  free (a);
255  free(filename);
256  return(S_EVFILE_BADFILE);
257  }
258  }
259  else
260  a->byte_swapped = 0;
261 
262  if(a->byte_swapped){
263  blk_size = int_swap_byte(header[EV_HD_BLKSIZ]);
264  a->buf = (int *)malloc(blk_size*4);
265  }
266  else
267  a->buf = (int *) malloc(header[EV_HD_BLKSIZ]*4);
268  if (!(a->buf)) {
269  free(a); /* if can't allocate buffer, give up */
270  free(filename);
271  return(S_EVFILE_ALLOCFAIL);
272  }
273  if(a->byte_swapped){
274  swapped_intcpy((char *)a->buf,(char *)header,EV_HDSIZ*4);
275  fread(&(a->buf[EV_HDSIZ]),4,blk_size-EV_HDSIZ,a->file);
276  }
277  else{
278  memcpy(a->buf,header,EV_HDSIZ*4);
279  fread(a->buf+EV_HDSIZ,4,
280  header[EV_HD_BLKSIZ]-EV_HDSIZ,
281  a->file); /* read rest of block */
282  }
283  a->next = a->buf + (a->buf)[EV_HD_START];
284  a->left = (a->buf)[EV_HD_USED] - (a->buf)[EV_HD_START];
285  }
286  break;
287  case 'w': case 'W':
288  a->rw = EV_WRITE;
289  if(strcmp(filename,"-")==0) {
290  a->file = stdout;
291  } else if(filename[0] == '|') {
292  a->file = popen(filename+1,"r");
293  a->rw = EV_PIPEWRITE; /* Make sure we know to use pclose */
294  } else {
295  a->file = fopen(filename,"w");
296  }
297  if (a->file) {
298  a->buf = (int *) malloc(EVBLOCKSIZE*4);
299  if (!(a->buf)) {
300  free(a);
301  free(filename);
302  return(S_EVFILE_ALLOCFAIL);
303  }
304  a->buf[EV_HD_BLKSIZ] = EVBLOCKSIZE;
305  a->buf[EV_HD_BLKNUM] = 0;
306  a->buf[EV_HD_HDSIZ] = EV_HDSIZ;
307  a->buf[EV_HD_START] = 0;
308  a->buf[EV_HD_USED] = EV_HDSIZ;
309  a->buf[EV_HD_VER] = EV_VERSION;
310  a->buf[EV_HD_RESVD] = 0;
311  a->buf[EV_HD_MAGIC] = EV_MAGIC;
312  a->next = a->buf + EV_HDSIZ;
313  a->left = EVBLOCKSIZE - EV_HDSIZ;
314  a->evnum = 0;
315  }
316  break;
317  default:
318  free(a);
319  free(filename);
320  return(S_EVFILE_UNKOPTION);
321  }
322  if (a->file) {
323  a->magic = EV_MAGIC;
324  a->blksiz = a->buf[EV_HD_BLKSIZ];
325  a->blknum = a->buf[EV_HD_BLKNUM];
326 #ifdef BIT64
327  for(ihandle=0;ihandle<MAXHANDLES;ihandle++){
328  if(handle_list[ihandle]==0) {
329  handle_list[ihandle] = a;
330  *handle = ihandle+1;
331  free(filename);
332  return(S_SUCCESS);
333  }
334  }
335  *handle = 0; /* No slots left */
336  free(a);
337  free(filename);
338  return(S_EVFILE_BADHANDLE); /* A better error code would help */
339 #else
340  *handle = (int) a;
341  free(filename);
342  return(S_SUCCESS);
343 #endif // BIT64
344  } else {
345  free(a);
346 #ifdef DEBUG
347  fprintf(stderr,"evOpen: Error opening file %s, flag %s\n",
348  filename,flags);
349  perror(NULL);
350 #endif
351  *handle = 0;
352  free(filename);
353  return(errno);
354  }
355  free(filename);
356 
357 }
358 
359 #ifdef AbsoftUNIXFortran
360 int evread
361 #else
363 #endif
364 (int *handle,int *buffer,int *buflen)
365 {
366  return(evRead(*handle,buffer,*buflen));
367 }
368 
369 int evRead(int handle,int *buffer,int buflen)
370 {
371  EVFILE *a;
372  int nleft,ncopy,error,status;
373  int *temp_buffer,*temp_ptr;
374 
375 #ifdef BIT64
376  a = handle_list[handle-1];
377 #else
378  a = (EVFILE *)handle;
379 #endif
380  if (a->byte_swapped){
381  temp_buffer = (int *)malloc(buflen*sizeof(int));
382  // cout << "tempbuffer9 = " << tempbuffer[9] << endl;
383  temp_ptr = temp_buffer;
384  }
385  if (a->magic != EV_MAGIC) return(S_EVFILE_BADHANDLE);
386  if (a->left<=0) {
387  error = evGetNewBuffer(a);
388  if (error) return(error);
389  }
390  if (a->byte_swapped)
391  nleft = int_swap_byte(*(a->next)) + 1;
392  else
393  nleft = *(a->next) + 1; /* inclusive size */
394  if (nleft < buflen) {
395  status = S_SUCCESS;
396  } else {
397  status = S_EVFILE_TRUNC;
398  nleft = buflen;
399  }
400  while (nleft>0) {
401  if (a->left<=0) {
402  error = evGetNewBuffer(a);
403  if (error) return(error);
404  }
405  ncopy = (nleft <= a->left) ? nleft : a->left;
406  if (a->byte_swapped){
407  memcpy(temp_buffer,a->next,ncopy*4);
408  temp_buffer += ncopy;
409  }
410  else{
411  memcpy(buffer,a->next,ncopy*4);
412  buffer += ncopy;
413  }
414  nleft -= ncopy;
415  a->next += ncopy;
416  a->left -= ncopy;
417  }
418  if (a->byte_swapped){
419  swapped_memcpy((char *)buffer,(char *)temp_ptr,buflen*sizeof(int));
420  free(temp_ptr);
421  }
422  return(status);
423 }
424 
426  EVFILE *a;
427 {
428  int i,nread,status;
429  status = S_SUCCESS;
430  if (feof(a->file)) return(EOF);
431  clearerr(a->file);
432  a->buf[EV_HD_MAGIC] = 0;
433  nread = fread(a->buf,4,a->blksiz,a->file);
434  if (a->byte_swapped){
435  for(i=0;i<EV_HDSIZ;i++)
436  onmemory_swap(&(a->buf[i]));
437  }
438  if (feof(a->file)) return(EOF);
439  if (ferror(a->file)) return(ferror(a->file));
440  if (nread != a->blksiz) return(errno);
441  if (a->buf[EV_HD_MAGIC] != EV_MAGIC) {
442  /* fprintf(stderr,"evRead: bad header\n"); */
443  return(S_EVFILE_BADFILE);
444  }
445  a->blknum++;
446  if (a->buf[EV_HD_BLKNUM] != a->blknum) {
447  /* fprintf(stderr,"evRead: bad block number %x should be %x\n",
448  a->buf[EV_HD_BLKNUM],a->blknum); */
449  status = S_EVFILE_BADBLOCK;
450  }
451  a->next = a->buf + (a->buf)[EV_HD_HDSIZ];
452  a->left = (a->buf)[EV_HD_USED] - (a->buf)[EV_HD_HDSIZ];
453  if (a->left<=0)
454  return(S_EVFILE_UNXPTDEOF);
455  else
456  return(status);
457 }
458 
459 #ifdef AbsoftUNIXFortran
460 int evwrite
461 #else
463 #endif
464 (int *handle,int *buffer)
465 {
466  return(evWrite(*handle,buffer));
467 }
468 
469 int evWrite(int handle,int *buffer)
470 {
471  EVFILE *a;
472  int nleft,ncopy,error;
473 #ifdef BIT64
474  a = handle_list[handle-1];
475 #else
476  a = (EVFILE *)handle;
477 #endif
478  if (a->magic != EV_MAGIC) return(S_EVFILE_BADHANDLE);
479  if (a->buf[EV_HD_START]==0) a->buf[EV_HD_START] = a->next - a->buf;
480  a->evnum = a->evnum + 1; /* increase ev number every time you call evWrite */
481  nleft = buffer[0] + 1; /* inclusive length */
482  while (nleft>0) {
483  ncopy = (nleft <= a->left) ? nleft : a->left;
484  memcpy(a->next,buffer,ncopy*4);
485  buffer += ncopy;
486  nleft -= ncopy;
487  a->next += ncopy;
488  a->left -= ncopy;
489  if (a->left<=0) {
490  error = evFlush(a);
491  if (error) return(error);
492  }
493  }
494  return(S_SUCCESS);
495 }
496 
497 int evFlush(a)
498  EVFILE *a;
499 {
500  int nwrite;
501  clearerr(a->file);
502  a->buf[EV_HD_USED] = a->next - a->buf;
503  a->buf[EV_HD_RESVD] = a->evnum;
504  nwrite = fwrite(a->buf,4,a->blksiz,a->file);
505  if (ferror(a->file)) return(ferror(a->file));
506  if (nwrite != a->blksiz) return(errno);
507  a->blknum++;
508  a->buf[EV_HD_BLKSIZ] = a->blksiz;
509  a->buf[EV_HD_BLKNUM] = a->blknum;
510  a->buf[EV_HD_HDSIZ] = EV_HDSIZ;
511  a->buf[EV_HD_START] = 0;
512  a->buf[EV_HD_USED] = EV_HDSIZ;
513  a->buf[EV_HD_VER] = EV_VERSION;
514  a->buf[EV_HD_RESVD] = 0;
515  a->buf[EV_HD_MAGIC] = EV_MAGIC;
516  a->next = a->buf + EV_HDSIZ;
517  a->left = a->blksiz - EV_HDSIZ;
518  return(S_SUCCESS);
519 }
520 
521 #ifdef AbsoftUNIXFortran
522 int evioctl
523 #else
525 #endif
526 (int *handle,char *request,void *argp,int reqlen)
527 {
528  char *req;
529  int status;
530  req = (char *)malloc(reqlen+1);
531  strncpy(req,request,reqlen);
532  req[reqlen]=0; /* insure request is null terminated */
533  status = evIoctl(*handle,req,argp);
534  free(req);
535  return(status);
536 }
537 
538 int evIoctl(int handle,char *request,void *argp)
539 {
540  EVFILE *a;
541 #ifdef BIT64
542  a = handle_list[handle-1];
543 #else
544  a = (EVFILE *)handle;
545 #endif
546  if (a->magic != EV_MAGIC) return(S_EVFILE_BADHANDLE);
547  switch (*request) {
548  case 'b': case 'B':
549  if (a->rw != EV_WRITE && a->rw != EV_PIPEWRITE) return(S_EVFILE_BADSIZEREQ);
550  if (a->blknum != 0) return(S_EVFILE_BADSIZEREQ);
551  if (a->buf[EV_HD_START] != 0) return(S_EVFILE_BADSIZEREQ);
552  free (a->buf);
553  a->blksiz = *(int *) argp;
554  a->left = a->blksiz - EV_HDSIZ;
555  a->buf = (int *) malloc(a->blksiz*4);
556  if (!(a->buf)) {
557  a->magic = 0;
558  free(a); /* if can't allocate buffer, give up */
559  return(S_EVFILE_ALLOCFAIL);
560  }
561  a->buf[EV_HD_BLKSIZ] = EVBLOCKSIZE;
562  a->buf[EV_HD_BLKNUM] = 0;
563  a->buf[EV_HD_HDSIZ] = EV_HDSIZ;
564  a->buf[EV_HD_START] = 0;
565  a->buf[EV_HD_USED] = EV_HDSIZ;
566  a->buf[EV_HD_VER] = EV_VERSION;
567  a->buf[EV_HD_RESVD] = 0;
568  a->buf[EV_HD_MAGIC] = EV_MAGIC;
569  break;
570  default:
571  return(S_EVFILE_UNKOPTION);
572  }
573  return(S_SUCCESS);
574 }
575 
576 #ifdef AbsoftUNIXFortran
577 int evclose
578 #else
580 #endif
581 (int *handle)
582 {
583  return(evClose(*handle));
584 }
585 
586 int evClose(int handle)
587 {
588  EVFILE *a;
589  int status, status2;
590 #ifdef BIT64
591  a = handle_list[handle-1];
592 #else
593  a = (EVFILE *)handle;
594 #endif
595  if (a->magic != EV_MAGIC) return(S_EVFILE_BADHANDLE);
596  if(a->rw == EV_WRITE || a->rw==EV_PIPEWRITE)
597  status = evFlush(a);
598  if(a->rw == EV_PIPE) {
599  status2 = pclose(a->file);
600  } else {
601  status2 = fclose(a->file);
602  }
603 #ifdef BIT64
604  handle_list[handle-1] = 0;
605 #endif
606  free((char *)(a->buf));
607  free((char *)a);
608  if (status==0) status = status2;
609  return(status);
610 }
611 
612 
613 /******************************************************************
614  * int evOpenSearch(int, int *) *
615  * Description: *
616  * Open for binary search on data blocks *
617  * return last physics event number *
618  *****************************************************************/
619 int evOpenSearch(int handle, int *b_handle)
620 {
621 #ifdef BIT64
622  int ihandle;
623 #endif
624  EVFILE *a;
625  EVBSEARCH *b;
626  int found = 0, temp, status, i = 1;
627  int last_evn, ev_type, bknum;
628  int header[EV_HDSIZ];
629 
630 #ifdef BIT64
631  a = handle_list[handle-1];
632 #else
633  a = (EVFILE *)handle;
634 #endif
635  b = (EVBSEARCH *)malloc(sizeof(EVBSEARCH));
636  if(b == NULL){
637  fprintf(stderr,"Cannot allocate memory for EVBSEARCH structure!\n");
638  exit(1);
639  }
640  fseek(a->file, 0L, SEEK_SET);
641  fread(header, sizeof(header), 1, a->file);
642  if(a->byte_swapped)
643  temp = int_swap_byte(header[EV_HD_BLKNUM]);
644  else
645  temp = header[EV_HD_BLKNUM];
646  b->sbk = temp;
647  /* jump to the end of file */
648  fseek(a->file, 0L, SEEK_END);
649  while(!found){
650  /* jump back to the beginning of the block */
651  fseek(a->file, (-1)*a->blksiz*4*i, SEEK_END);
652  if((bknum = physicsEventsInsideBlock(a)) >= 0){
653  b->ebk = bknum;
654  break;
655  }
656  else
657  i++;
658  }
659  /* the file pointer will point to the first physics event in the block */
660  last_evn = findLastEventWithinBlock(a);
661  b->found_bk = -1;
662  b->found_evn = -1;
663  b->last_evn = last_evn;
664 #ifdef BIT64
665  for(ihandle=0;ihandle<MAXHANDLES;ihandle++){
666  if(handle_list[ihandle]==0) {
667  handle_list[ihandle] = (EVFILE *)b;
668  *b_handle = ihandle+1;
669  return last_evn;
670  }
671  }
672  *b_handle = 0; /* No slots left */
673  free(b);
674  return(-1); /* A better error code would help */
675 #else
676  *b_handle = (int) b;
677  return last_evn;
678 #endif // BIT64
679 }
680 
681 /*********************************************************************
682  * static int findLastEventWithinBlock(EVFILE *) *
683  * Description: *
684  * Doing sequential search on a block pointed by a *
685  * return last event number in the block *
686  * the pointer to the file has been moved to the beginning *
687  * of the fisrt event already by evOpenSearch() *
688  ********************************************************************/
690 {
691  int header, t_header, found = 0;
692  int ev_size, temp, evn = 0, last_evn = 0;
693  int ev_type;
694  int first_time = 0;
695 
696  while(!found){
697  fread(&header, sizeof(int), 1, a->file);
698  if(a->byte_swapped)
699  ev_size = int_swap_byte(header) + 1;
700  else
701  ev_size = header + 1;
702  /* read event type */
703  ev_type = evGetEventType(a);
704  a->left = a->left - ev_size; /* file pointer stays */
705  if(a->left <= 0){ /* no need to distinguish the special event */
706  if(ev_type < 16){ /* physics event */
707  first_time++;
708  fseek(a->file, 3*4, SEEK_CUR);
709  fread(&header, sizeof(int), 1, a->file);
710  if(a->byte_swapped)
711  evn = int_swap_byte(header);
712  else
713  evn = header;
714  found = 1;
715  }
716  else{
717  if (first_time == 0){
718  evn = -1;
719  found = 1;
720  }
721  else{
722  evn = last_evn;
723  found = 1;
724  }
725  }
726  }
727  else{
728  if(ev_type < 16){
729  first_time++;
730  fseek(a->file, 3*4, SEEK_CUR);
731  fread(&header, sizeof(int), 1, a->file);
732  if(a->byte_swapped)
733  evn = int_swap_byte(header);
734  else
735  evn = header;
736  last_evn = evn;
737  fseek(a->file,(ev_size - 5)*4, SEEK_CUR);
738  }
739  else{
740  fseek(a->file, (ev_size - 1)*4, SEEK_CUR);
741  }
742  }
743  }
744  return evn;
745 }
746 
747 /********************************************************************
748  * int evSearch(int, int, int, int *, int, int *) *
749  * Description: *
750  * Doing binary search for event number evn, -1 failure *
751  * Copy event to buffer with buffer length buflen *
752  * This routine must be called after evOpenSearch() *
753  * return 0: found the event *
754  * return -1: the event number bigger than largest ev number *
755  * return 1: cannot find the event number *
756  *******************************************************************/
757 int evSearch(int handle, int b_handle, int evn, int *buffer, int buflen, int *size)
758 {
759  EVFILE *a;
760  EVBSEARCH *b;
761  int start,end, mid;
762  int found;
763 
764 #ifdef BIT64
765  a = handle_list[handle-1];
766  b = (EVBSEARCH *)handle_list[b_handle-1];
767 #else
768  a = (EVFILE *)handle;
769  b = (EVBSEARCH *)b_handle;
770 #endif
771 
772  if(evn > b->last_evn)
773  return -1;
774 
775  if(b->found_bk < 0){
776  start = b->sbk;
777  end = b->ebk;
778  mid = (start + end)/2.0;
779  }
780  else{
781  if(evn >= b->found_evn){
782  start = b->found_bk;
783  end = b->ebk;
784  mid = (start + end)/2.0;
785  }
786  else{
787  start = b->sbk;
788  end = b->found_bk;
789  mid = (start + end)/2.0;
790  }
791  }
792  while(start <= end){
793  found = evSearchWithinBlock(a, b, &mid, evn, buffer, buflen, size);
794  if(found < 0){ /* lower block */
795  end = mid - 1;
796  mid = (start + end)/2.0;
797  }
798  else if(found > 0){ /* upper block */
799  start = mid + 1;
800  mid = (start + end)/2.0;
801  }
802  else if(found == 0){ /*found block and evn */
803  break;
804  }
805  else
806  return found;
807  }
808  if(start <= end){
809  b->found_bk = mid;
810  b->found_evn = evn;
811  return 0;
812  }
813  else{
814  b->found_bk = -1;
815  return 1;
816  }
817 }
818 
819 
820 /****************************************************************************
821  * static int evSearchWithinBlock(EVFILE *, EVBSEARCH *, int *,int, int * *
822  * int, int * ) *
823  * Description: *
824  * Doing sequential search on a particular block to find out event *
825  * number evn *
826  * return 0: found *
827  * return -1: evn < all events in the block *
828  * return 1: evn > all events in the block *
829  ***************************************************************************/
830 static int evSearchWithinBlock(EVFILE *a, EVBSEARCH *b, int *bknum,
831  int evn, int *buffer, int buflen, int *size)
832 {
833  int header[EV_HDSIZ], temp, ev_size;
834  int buf[EV_HDSIZ], status;
835  int found = 0, t_evn, block_num;
836  int ev_type, t_temp;
837 
838  evFindEventBlockNum(a, b, bknum);
839  block_num = *bknum;
840 
841  /* check first event, if its event number is greater than
842  * requested event number, return -1
843  * the pointer pointing to file has been moved in the previous
844  * subroutines
845  */
846  fread(&temp,sizeof(int),1,a->file);
847  if(a->byte_swapped)
848  ev_size = int_swap_byte(temp) + 1;
849  else
850  ev_size = temp + 1;
851 
852  a->left = a->left - ev_size;
853  t_evn = evGetEventNumber(a, ev_size); /* file pointer stays here */
854 
855  if(t_evn == evn){
856  fseek(a->file, (-1)*4, SEEK_CUR); /* go to top of event */
857  *size = ev_size;
858  status = copySingleEvent(a, buffer, buflen, ev_size);
859  return status;
860  }
861  else if(t_evn > evn) /* no need to search any more */
862  return -1;
863  else{ /* need to search more */
864  if(a->left <=0) /* no more events left */
865  return 1;
866  else{
867  fseek(a->file, (ev_size-1)*4, SEEK_CUR);
868  while(!found && a->left > 0){
869  fread(&temp, sizeof(int), 1, a->file);
870  if(a->byte_swapped)
871  ev_size = int_swap_byte(temp) + 1;
872  else
873  ev_size = temp + 1;
874  /* read event type */
875  ev_type = evGetEventType(a); /* file pointer fixed here */
876 
877  a->left = a->left - ev_size;
878  if(a->left <= 0){ /* this is the last event */
879  if(ev_type < 16){ /* physics event here */
880  t_evn = evGetEventNumber(a, ev_size); /* pinter stays */
881  /* check current event number */
882  if(t_evn == evn){
883  fseek(a->file, (-1)*4, SEEK_CUR);
884  found = 1;
885  *size = ev_size;
886  return (copySingleEvent(a, buffer, buflen, ev_size));
887  }
888  else
889  return 1;
890  }
891  else /* last event is not a physics event, no match */
892  return 1;
893  }
894  else{ /* not last event */
895  if(ev_type < 16){
896  t_evn = evGetEventNumber(a, ev_size);
897  /* check current event number */
898  if(t_evn == evn){
899  fseek(a->file, (-1)*4, SEEK_CUR);
900  *size = ev_size;
901  found = 1;
902  return (copySingleEvent(a, buffer, buflen, ev_size));
903  }
904  else{ /* go to next event */
905  fseek(a->file, (ev_size-1)*4, SEEK_CUR);
906  }
907  }
908  else /* special event go to next event */
909  fseek(a->file, (ev_size - 1)*4, SEEK_CUR);
910  } /* end of not last event case*/
911  } /* end of search event loop*/
912  }
913  }
914 }
915 
916 
917 /********************************************************************
918  * static void evFindEventBlockNum(EVFILE *, EVBSEARCH *, int *) *
919  * Description: *
920  * find out real block number in the case of this block *
921  * has one big event just crossing it *
922  *******************************************************************/
923 static void evFindEventBlockNum(EVFILE *a, EVBSEARCH *b, int *bknum)
924 {
925  int header[EV_HDSIZ], block_num;
926  int buf[EV_HDSIZ];
927  int found = 0, temp, nleft;
928 
929  block_num = *bknum;
930  while(block_num <= b->ebk){
931  fseek(a->file, a->blksiz*block_num*4, SEEK_SET);
932  fread(header, sizeof(header), 1, a->file);
933  if(a->byte_swapped)
934  swapped_intcpy((char *)buf, (char *)header, EV_HDSIZ*4);
935  else
936  memcpy(buf, header, EV_HDSIZ*4);
937  if(buf[EV_HD_START] > 0){
938  fseek(a->file, 4*(buf[EV_HD_START]-EV_HDSIZ), SEEK_CUR);
939  nleft = buf[EV_HD_USED] - buf[EV_HD_START];
940  if(isRealEventsInsideBlock(a,block_num,nleft)){
941  *bknum = block_num;
942  return;
943  }
944  block_num++;
945  }
946  else
947  block_num++;
948  }
949  /* cannot find right block this way, try reverse direction */
950  block_num = *bknum;
951  while(block_num >= b->sbk){
952  fseek(a->file, a->blksiz*block_num*4, SEEK_SET);
953  fread(header, sizeof(header), 1, a->file);
954  if(a->byte_swapped)
955  swapped_intcpy((char *)buf,(char *)header, EV_HDSIZ*4);
956  else
957  memcpy((char *)buf, (char *)header, EV_HDSIZ*4);
958  if(buf[EV_HD_START] > 0){
959  fseek(a->file, 4*(buf[EV_HD_START]-EV_HDSIZ), SEEK_CUR);
960  nleft = buf[EV_HD_USED] - buf[EV_HD_START];
961  if(isRealEventsInsideBlock(a,block_num, nleft)){
962  *bknum = block_num;
963  return;
964  }
965  block_num--;
966  }
967  else
968  block_num--;
969  }
970  fprintf(stderr,"Cannot find out event offset in any of the blocks, Exit!\n");
971  exit(1);
972 }
973 
974 /*************************************************************************
975  * static int isRealEventInsideBlock(EVFILE *, int, int) *
976  * Description: *
977  * Find out whether there is a real event inside this block *
978  * return 1: yes, return 0: no *
979  ************************************************************************/
980 static int isRealEventsInsideBlock(EVFILE *a, int bknum, int old_left)
981 {
982  int nleft = old_left;
983  int ev_size, temp, ev_type;
984 
985  while(nleft > 0){
986  fread(&temp, sizeof(int), 1, a->file);
987  if(a->byte_swapped)
988  ev_size = int_swap_byte(temp) + 1;
989  else
990  ev_size = temp + 1;
991 
992  ev_type = evGetEventType(a); /* file pointer stays */
993  if(ev_type < 16){
994  fseek(a->file, (-1)*sizeof(int), SEEK_CUR); /* rewind to head of this event */
995  break;
996  }
997  else{
998  nleft = nleft - ev_size;
999  fseek(a->file, 4*(ev_size - 1), SEEK_CUR);
1000  }
1001  }
1002  if(nleft <= 0)
1003  return 0;
1004  else{
1005  a->left = nleft;
1006  return 1;
1007  }
1008 }
1009 
1010 /*****************************************************************************
1011  * static int copySingleEvent(EVFILE *, int *, int, int) *
1012  * Description: *
1013  * copy a single event to buffer by using fread. *
1014  * starting point is given by EVFILE *a *
1015  ****************************************************************************/
1016 static int copySingleEvent(EVFILE *a, int *buffer, int buflen, int ev_size)
1017 {
1018  int *temp_buffer, *temp_ptr, *ptr;
1019  int status, nleft, temp, block_left;
1020  int ncopy;
1021 
1022 
1023  if(a->byte_swapped){
1024  temp_buffer = (int *)malloc(buflen*sizeof(int));
1025  temp_ptr = temp_buffer;
1026  }
1027  else{
1028  ptr = buffer;
1029  }
1030 
1031  if(buflen < ev_size){
1032  status = S_EVFILE_TRUNC;
1033  nleft = buflen;
1034  }
1035  else{
1036  status = S_SUCCESS;
1037  nleft = ev_size;
1038  }
1039  if(a->left < 0){
1040  block_left = ev_size + a->left;
1041  if(nleft <= block_left){
1042  if(a->byte_swapped){
1043  fread((char *)temp_ptr, nleft*4, 1, a->file);
1044  }
1045  else
1046  fread((char *)ptr, nleft*4, 1, a->file);
1047  }
1048  else{
1049  ncopy = block_left;
1050  while(nleft > 0){
1051  if(a->byte_swapped){
1052  fread((char *)temp_ptr, ncopy*4, 1, a->file);
1053  temp_ptr = temp_ptr + ncopy;
1054  }
1055  else{
1056  fread((char *)ptr, ncopy*4, 1, a->file);
1057  ptr = ptr + ncopy;
1058  }
1059  nleft = nleft - ncopy;
1060  if(nleft > a->blksiz - EV_HDSIZ){
1061  fseek(a->file, EV_HDSIZ*4, SEEK_CUR);
1062  ncopy = a->blksiz - EV_HDSIZ;
1063  }
1064  else if(nleft > 0){
1065  fseek(a->file, EV_HDSIZ*4,SEEK_CUR);
1066  ncopy = nleft;
1067  }
1068  }
1069  if(a->byte_swapped)
1070  temp_ptr = temp_buffer;
1071  else
1072  ptr = buffer;
1073  }
1074  }
1075  else{
1076  if(a->byte_swapped){
1077  fread(temp_ptr, ev_size*4, 1, a->file);
1078  }
1079  else{
1080  fread(ptr, ev_size*4, 1, a->file);
1081  }
1082  }
1083 
1084  if(a->byte_swapped){
1085  swapped_memcpy((char *)buffer, (char *)temp_ptr, buflen*sizeof(int));
1086  free(temp_ptr);
1087  }
1088  return (status);
1089 }
1090 
1091 /***********************************************************************
1092  * int evCloseSearch(int ) *
1093  * Description: *
1094  * Close evSearch process, release memory *
1095  **********************************************************************/
1096 int evCloseSearch(int b_handle)
1097 {
1098  EVBSEARCH *b;
1099 #ifdef BIT64
1100  b = (EVBSEARCH *)handle_list[b_handle-1];
1101  handle_list[b_handle-1] = 0;
1102 #else
1103  b = (EVBSEARCH *)b_handle;
1104 #endif
1105  free((char *)b);
1106 }
1107 
1108 /**********************************************************************
1109  * static int evGeteventNumber(EVFILE *, int) *
1110  * Description: *
1111  * get event number starting from event head. *
1112  *********************************************************************/
1113 static int evGetEventNumber(EVFILE *a, int ev_size)
1114 {
1115  int temp, evn, nleft;
1116 
1117  nleft = a->left + ev_size;
1118  if(nleft >= 5)
1119  fseek(a->file, 3*4, SEEK_CUR);
1120  else
1121  fseek(a->file, (EV_HDSIZ+3)*4, SEEK_CUR);
1122  fread(&temp, sizeof(int), 1, a->file);
1123  if(a->byte_swapped)
1124  evn = int_swap_byte(temp);
1125  else
1126  evn = temp;
1127 
1128  if(nleft >= 5)
1129  fseek(a->file, (-1)*4*4, SEEK_CUR);
1130  else
1131  fseek(a->file,(-1)*(EV_HDSIZ + 4)*4, SEEK_CUR);
1132 
1133  return evn;
1134 }
1135 
1136 static int evGetEventType(EVFILE *a)
1137 {
1138  int ev_type, temp, t_temp;
1139 
1140  if(a->left == 1) /* event type long word is in the following block */
1141  fseek(a->file, (EV_HDSIZ)*4,SEEK_CUR);
1142  if(a->byte_swapped){
1143  fread(&t_temp, sizeof(int), 1, a->file);
1144  swapped_intcpy((char *)&temp, (char *)&t_temp, sizeof(int));
1145  }
1146  else
1147  fread(&temp, sizeof(int), 1, a->file);
1148  ev_type = (temp >> 16)&(0x0000ffff);
1149 
1150  if(a->left == 1)
1151  fseek(a->file, (-1)*(EV_HDSIZ + 1)*4, SEEK_CUR);
1152  else
1153  fseek(a->file, (-1)*4, SEEK_CUR);
1154 
1155  return ev_type;
1156 }
1157 
1158 
1159 /*************************************************************************
1160  * static int physicsEventsInsideBlock(a) *
1161  * Description: *
1162  * Check out whether this block pointed by a contains any physics *
1163  * events *
1164  * return -1: contains no physics *
1165  * return >= 0 : yes, contains physics event, with block number *
1166  * the file pointer will stays at the begining of the first physics *
1167  * event inside the block *
1168  ************************************************************************/
1170 {
1171  int header[EV_HDSIZ], buf[EV_HDSIZ];
1172  int nleft, temp, ev_size, ev_type;
1173 
1174  /* copy block header information */
1175  if(a->byte_swapped){
1176  fread(header, sizeof(header), 1, a->file);
1177  swapped_intcpy((char *)buf, (char *)header, EV_HDSIZ*4);
1178  }
1179  else
1180  fread(buf, sizeof(buf), 1, a->file);
1181  /* search first event inside this block */
1182  if (buf[EV_HD_START] < 0)
1183  return 0;
1184  else{
1185  /* jump to the first event */
1186  fseek(a->file, 4*(buf[EV_HD_START] - EV_HDSIZ), SEEK_CUR);
1187  nleft = buf[EV_HD_USED] - buf[EV_HD_START];
1188  while (nleft > 0){
1189  fread(&temp, sizeof(int), 1, a->file);
1190  if(a->byte_swapped)
1191  ev_size = int_swap_byte(temp) + 1;
1192  else
1193  ev_size = temp + 1;
1194  /* check event type and file pointer stays */
1195  ev_type = evGetEventType(a);
1196  if(ev_type < 16) { /*physics event */
1197  fseek(a->file, (-1)*sizeof(int), SEEK_CUR);
1198  a->left = nleft;
1199  return buf[EV_HD_BLKNUM];
1200  }
1201  else{
1202  nleft = nleft - ev_size;
1203  fseek(a->file, 4*(ev_size - 1), SEEK_CUR);
1204  }
1205  }
1206  }
1207  return 0;
1208 }
#define NULL
Definition: Pdb.h:9
#define S_EVFILE_UNKOPTION
Definition: evfile_msg.h:15
#define S_EVFILE_BADSIZEREQ
Definition: evfile_msg.h:17
#define S_EVFILE_BADBLOCK
Definition: evfile_msg.h:11
#define S_EVFILE_BADFILE
Definition: evfile_msg.h:14
#define S_EVFILE_TRUNC
Definition: evfile_msg.h:10
#define S_EVFILE_UNXPTDEOF
Definition: evfile_msg.h:16
#define S_EVFILE_BADHANDLE
Definition: evfile_msg.h:12
#define S_SUCCESS
Definition: evfile_msg.h:5
#define S_EVFILE_ALLOCFAIL
Definition: evfile_msg.h:13
int evSearch(int handle, int b_handle, int evn, int *buffer, int buflen, int *size)
Definition: evio.c:757
int evwrite_(int *handle, int *buffer)
Definition: evio.c:464
#define EV_HD_VER
Definition: evio.c:126
#define EV_PIPE
Definition: evio.c:114
#define EV_WRITE
Definition: evio.c:113
#define EV_HD_BLKSIZ
Definition: evio.c:121
int evClose(int handle)
Definition: evio.c:586
int swapped_fread()
#define EV_PIPEWRITE
Definition: evio.c:115
static int evGetEventType(EVFILE *)
Definition: evio.c:1136
#define EV_HD_MAGIC
Definition: evio.c:128
int evOpenSearch(int handle, int *b_handle)
Definition: evio.c:619
int evopen_(char *filename, char *flags, int *handle, int fnlen, int flen)
Definition: evio.c:161
#define EV_HD_BLKNUM
Definition: evio.c:122
#define EV_VERSION
Definition: evio.c:116
struct evBinarySearch EVBSEARCH
#define EV_READ
Definition: evio.c:112
#define EV_HD_HDSIZ
Definition: evio.c:123
static int isRealEventsInsideBlock(EVFILE *, int, int)
Definition: evio.c:980
int evCloseSearch(int b_handle)
Definition: evio.c:1096
#define EVBLOCKSIZE
Definition: evio.c:111
static void evFindEventBlockNum(EVFILE *, EVBSEARCH *, int *)
Definition: evio.c:923
void swapped_intcpy()
int evioctl_(int *handle, char *request, void *argp, int reqlen)
Definition: evio.c:526
int evWrite(int handle, int *buffer)
Definition: evio.c:469
static int findLastEventWithinBlock(EVFILE *)
Definition: evio.c:689
void swapped_memcpy()
#define EV_HD_RESVD
Definition: evio.c:127
#define evGetStructure()
Definition: evio.c:130
static int evSearchWithinBlock(EVFILE *, EVBSEARCH *, int *, int, int *, int, int *)
Definition: evio.c:830
static int physicsEventsInsideBlock(EVFILE *)
Definition: evio.c:1169
#define EV_HDSIZ
Definition: evio.c:118
int evOpen(char *fname, char *flags, int *handle)
Definition: evio.c:187
static int copySingleEvent(EVFILE *, int *, int, int)
Definition: evio.c:1016
static char * kill_trailing(char *s, char t)
Definition: evio.c:177
int evFlush(EVFILE *a)
Definition: evio.c:497
int evRead(int handle, int *buffer, int buflen)
Definition: evio.c:369
int evclose_(int *handle)
Definition: evio.c:581
int evread_(int *handle, int *buffer, int *buflen)
Definition: evio.c:364
#define EV_HD_USED
Definition: evio.c:125
void onmemory_swap()
int evIoctl(int handle, char *request, void *argp)
Definition: evio.c:538
static int evGetEventNumber(EVFILE *, int)
Definition: evio.c:1113
#define EV_HD_START
Definition: evio.c:124
int int_swap_byte()
#define EV_MAGIC
Definition: evio.c:117
int evGetNewBuffer(EVFILE *a)
Definition: evio.c:425
struct evfilestruct EVFILE