source: trunk/src/libsrc/util/sudsputaway.c @ 7513

Revision 7513, 28.2 KB checked in by baker, 6 months ago (diff)

cleanup warning: variable set but not used [-Wunused-but-set-variable]

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/* sudsputaway.c
2   
3        Routines for writing trace data in PC-SUDS format
4
5
6  Thu Jul 22 14:56:37 MDT 1999 Lucky Vidmar
7    Major structural changes to accomodate making all putaway routines
8    into library calls so that they can be shared between trig2disk
9    and wave2disk. Eliminated global variables set and allocated outside
10    of this file. We should only have static globals from now on, with
11    everything else being passed in via the putaway.c calls.
12*/
13
14#include <errno.h>
15#include <inttypes.h>
16#include <limits.h>
17#include <stdio.h>
18#include <stdlib.h>
19#include <string.h>
20#include <time.h>
21
22#include "earthworm.h"
23#include "trace_buf.h"
24#include "swap.h"
25#include "ws_clientII.h"
26#include "sudshead.h"
27#include "pa_subs.h"
28
29#define TAG_FILE        '.tag'        /* file containing the last known file tag */
30#define MAXTXT           150
31
32FILE    *SUDSfp;                      /* file pointer for the SUDS file */
33
34static  int32_t  *SudsBuffer;         /* write out SUDS data as 32-bit integers */
35static  short  *SudsBufferShort;      /* write out SUDS data as short integers */
36static  char SudsOutputFormat[MAXTXT];
37
38/* Internal Function Prototypes */
39static int StructMakeLocal (void *, int, char, int);
40static int SwapDo (void *, int);
41
42/************************************************************************
43* Initialization functionfor SUDS_STRUCTTAG structure,                  *                                             *
44*       Initialize the SUDS_STRUCTTAG structure    .                    *
45*                                                                       *
46*************************************************************************/
47void init_struct_SUDS_STRUCTTAG(SUDS_STRUCTTAG *tag)
48{
49  tag->sync = 'S';
50  tag->machine = NOCHAR;
51  tag->id_struct = (SH_INT)atoi(NODATA);
52  tag->len_struct = atol(NODATA);
53  tag->len_data = atol(NODATA);
54}
55/************************************************************************
56* Initialization functionfor SUDS_STATIONCOMP structure,                *                                             *
57*       Initialize the SUDS_STATIONCOMP structure    .                  *
58*                                                                       *
59*************************************************************************/
60void init_struct_SUDS_STATIONCOMP(SUDS_STATIONCOMP *sc)
61{
62  strcpy(sc->sc_name.network, NOSTRG);
63  strcpy(sc->sc_name.st_name, NOSTRG);
64  sc->sc_name. component = NOCHAR;
65  /* Where do we put SEED location code? */
66  sc->sc_name.inst_type = (SH_INT)atoi(NOLIST);
67
68  sc->azim = (SH_INT)atoi(NODATA);
69  sc->incid = (SH_INT)atoi(NODATA);
70  sc->st_lat = atof(NODATA);
71  sc->st_long = atof(NODATA);
72  sc->elev = (float)atof(NODATA);
73  sc->enclosure = NOCHAR;
74  sc->annotation = (CHAR)atoi(NOLIST);
75  sc->recorder = NOCHAR;
76  sc->rockclass = NOCHAR;
77  sc->rocktype = (SH_INT)atoi(NOLIST);
78  sc->sitecondition = NOCHAR;
79  sc->sensor_type = NOCHAR;
80  sc->data_type = NOCHAR;
81  sc->data_units = NOCHAR;
82  sc->polarity = NOCHAR;
83  sc->st_status = (CHAR)atoi(NOLIST);
84  sc->max_gain = (float)atof(NODATA);
85  sc->clip_value = (float)atof(NODATA);
86  sc->con_mvolts = (float)atof(NODATA);
87  sc->channel = (SH_INT)atoi(NODATA);
88  sc->atod_gain = (SH_INT)atoi(NODATA);
89  sc->effective = atol(NOTIME);
90  sc->clock_correct = (float)0.0;
91  sc->station_delay = (float)0.0;
92}
93
94/************************************************************************
95* Initialization functionfor SUDS_DESCRIPTRACE structure,               *                                             *
96*       Initialize the SUDS_DESCRIPTRACE structure   .                  *
97*                                                                       *
98*************************************************************************/
99void init_struct_SUDS_DESCRIPTRACE(SUDS_DESCRIPTRACE *dt)
100{
101  strcpy(dt->dt_name.network, NOSTRG);
102  strcpy(dt->dt_name.st_name, NOSTRG);
103  dt->dt_name. component = NOCHAR;
104  dt->dt_name.inst_type = (SH_INT)atoi(NOLIST);
105
106  dt->localtime = (SH_INT)atoi(NODATA);
107  dt->datatype = NOCHAR;
108  dt->descriptor = NOCHAR;
109  dt->digi_by = (SH_INT)atoi(NOLIST);
110  dt->processed = (SH_INT)atoi(NOLIST);
111  dt->length = atol(NODATA);
112  dt->rate = (float)atof(NODATA);
113  dt->mindata = (float)atof(NODATA);
114  dt->maxdata = (float)atof(NODATA);
115  dt->avenoise = (float)atof(NODATA);
116  dt->numclip = atol(NODATA);
117  dt->time_correct = atol("0.0");
118  dt->rate_correct = (float)0.0;
119}
120
121/************************************************************************
122* Initialization function,                                              *
123*       This is the Put Away startup intializer. This is called when    *
124*       the system first comes up. Here is a chance to look around      *
125*       and see if it's possible to do business, and to complain        *
126*       if not ,BEFORE an event has to be processed.                    *
127*                                                                       *
128*       For PCSUDS, all we want to do is to make sure that the          *
129*       directory where files should be written exists.                 *
130*************************************************************************/
131int SUDSPA_init (int OutBufferLen, char *OutDir, char *OutputFormat, 
132                 int debug)
133{
134  /** Allocate SudsBuffer and SudsBufferShort
135       We waste RAM by allocating both the int32 and short buffers here
136         at the beginning of the code because some fluke (feature?) of NT
137         which I don't understand becomes unhappy if we do the allocation
138        later. Win2000, of course, behaves differently, and is quite happy
139        with buffer allocation after we have determined the format of the
140        incoming data */
141  if ((SudsBuffer = (int32_t *) malloc (OutBufferLen * sizeof (char))) == NULL)
142  {
143    logit ("et", "SUDSPA_init: couldn't malloc SudsBuffer\n");
144    return EW_FAILURE;
145  }
146  if ((SudsBufferShort = (short *) malloc (OutBufferLen * sizeof (char))) == NULL)
147  {
148    logit ("et", "SUDSPA_init: couldn't malloc SudsBufferShort\n");
149    return EW_FAILURE;
150  }
151
152  /* Make sure that the top level output directory exists */
153  if (CreateDir (OutDir) != EW_SUCCESS)
154  {
155    logit ("e", "SUDSPA_init: Call to CreateDir failed\n");
156    return EW_FAILURE;
157  }
158
159  if(strlen(OutputFormat) >= sizeof(SudsOutputFormat))
160  {
161    logit("","SUDSPA_init: Error: OutputFormat(%s) is too long! Quitting!\n",
162          OutputFormat);
163    return(EW_FAILURE);
164  }
165  else
166  {
167    strcpy(SudsOutputFormat,OutputFormat);
168  }
169  return EW_SUCCESS; 
170}
171
172/************************************************************************
173*   This is the Put Away event initializer. It's called when a snippet  *
174*   has been received, and is about to be processed.                    *
175*   It gets to see the pointer to the TraceRequest array,               *
176*   and the number of loaded trace structures.                          *
177*                                                                       *
178*   For PCSUDS, we need to make sure that the target directory          *
179*   exists, create it if it does not, then open the SUDS file           *
180*   for writing.                                                        *
181*************************************************************************/
182int SUDSPA_next_ev (char *EventID, TRACE_REQ *ptrReq, int nReq, 
183                    char *OutDir, char *EventDate, char *EventTime,
184                    char *EventSubnet, int debug)
185
186{
187  char    SUDSFile[4*MAXTXT];
188  char    hhmmss[7];
189
190  /* Changed by Eugene Lublinsky, 3/31/Y2K */
191  /* There are 2 modes of behavior now: the default one when insmod */
192  /* is numeric or the second one when insmod is alphanumeric */
193  char  tmpEventID[EVENTID_SIZE + 3];
194
195  /* We treat suds file slightly differently - by request
196   * from Tom Murray. The files are placed directly into the
197   * top level suds directory, with names as follows:
198   *
199   *    yyyymmdd_hhmmss_insmod_evid.dmx
200   */
201
202  /* Changed by Eugene Lublinsky, 3/31/Y2K */
203  /* choose which way to go */
204
205  /* Build the file name */
206  /* added by murray (and it shows) to set the eventid at 3 characters */
207  if (strlen(EventID) < 3)
208    sprintf (tmpEventID,"000%s",EventID) ;
209  else
210    sprintf (tmpEventID,"%s",EventID) ;
211
212  /* ensure that time string is of the form hhmmss (revised EventTime
213     allows a string of the form hhmmss.ss, so truncate it if necessary) */
214  if (strlen(EventTime) > 6)
215  {
216    strncpy(hhmmss, EventTime, 6);
217    hhmmss[6] = '\0';
218  }
219  else
220    strcpy(hhmmss, EventTime);
221
222  /* changed by Carol 3/21/01: if no subnet, use network name
223     in filename */
224  if (EventSubnet[0] != '\0')
225    sprintf (SUDSFile, "%s/%s_%s_%s_%s.dmx", OutDir,
226             EventDate, hhmmss, EventSubnet, 
227             &tmpEventID[strlen(tmpEventID)-3]);
228  else
229    sprintf (SUDSFile, "%s/%s_%s_%s_%s.dmx", OutDir,
230             EventDate, hhmmss, ptrReq->net, 
231             &tmpEventID[strlen(tmpEventID)-3]);
232       
233  /* end of changes */
234
235  if (debug == 1)
236    logit ("t", "Opening SUDS file %s\n", SUDSFile);
237
238  /* open file */
239  if ((SUDSfp = fopen (SUDSFile, "wb")) == NULL)
240  {
241    logit ("e", "SUDSPA_next_ev: unable to open file %s: %s\n", 
242           SUDSFile, strerror(errno));
243    return EW_FAILURE;
244  }
245
246  return (EW_SUCCESS);
247}
248
249/************************************************************************
250* This is the working entry point into the disposal system. This        *
251* routine gets called for each trace snippet which has been recovered.  *
252* It gets to see the corresponding SNIPPET structure, and the event id  *
253*                                                                       *
254* For PCSUDS, this routine writes to the SUDS file, pointed to by the   *
255* SUDSfp pointer, all of the received trace data in SUDS format:        *
256*                                                                       *
257*      1. SUDS tag - indicating what follows                            *
258*      2. SUDS_STATIONCOMP struct - describe the station                *
259*      3. SUDS tag - indicating what follows                            *
260*      4. SUDS_DESCRIPTRACE struct - describe the trace data            *
261*      5. trace data                                                    *
262*                                                                       *
263*  One bit of complexity is that we need to write the files in the      *
264*  correct byte-order. Based on the OutputFormat parameter, determine   *
265*  whether or not to swap bytes before writing the suds file.           *
266*                                                                       *
267* WARNING: we clip trace data to -2147483648 - +2147483647 so it will   *
268*  fit in a 32-bit int. Any incoming data that is longer than 32 bits   *
269*  will be CLIPPED. cjb 5/18/2001                                       *
270*************************************************************************/
271/* Process one channel of data */
272int SUDSPA_next (TRACE_REQ *getThis, double GapThresh,
273                 long OutBufferLen, int debug)
274{
275  TRACE2_HEADER *wf;
276  short  *s_data;
277  int32_t *l_data = NULL;
278  char   *msg_p;        /* pointer into tracebuf data */
279  char    datatype;
280  int     data_size;
281  int     j;
282  int     gap_count = 0;
283  long    nsamp, nfill;
284  long    nfill_max = 0l;
285  long    nsamp_this_scn = 0l;
286  long    this_size;
287  double  begintime, starttime, endtime;
288  double  samprate;
289  int32_t fill = 0l;
290  long    min, max;
291  int     total;
292  SUDS_STRUCTTAG          tag;
293  SUDS_DESCRIPTRACE       dt;
294  SUDS_STATIONCOMP        sc;
295 
296  /* Check arguments */
297  if (getThis == NULL)
298  {
299    logit ("e", "SUDSPA_next: invalid argument passed in.\n");
300    return EW_FAILURE;
301  }
302
303  /* Start with a clean slate */
304  memset(&tag, 0, sizeof(tag));
305  init_struct_SUDS_STRUCTTAG(&tag);
306  memset(&dt, 0, sizeof(dt));
307  init_struct_SUDS_DESCRIPTRACE(&dt);
308  memset(&sc, 0, sizeof(sc));
309  init_struct_SUDS_STATIONCOMP(&sc);
310 
311  /* Used for computing trace statistics */
312  max = 4096;
313  min = 0;
314  total = 0;
315
316  if ( (msg_p = getThis->pBuf) == NULL)   /* pointer to first message */
317  {
318    logit ("e", "SUDSPA_next: Message buffer is NULL.\n");
319    return EW_FAILURE;
320  }
321  wf = (TRACE2_HEADER *) msg_p;
322 
323  /* Look at the first TRACE2_HEADER and get set up of action */
324  if (WaveMsg2MakeLocal(wf) < 0)
325  {
326    logit("e", "SUDSPA_next: unknown trace data type: %s\n",
327          wf->datatype);
328    return( EW_FAILURE );
329  }
330
331  nsamp = wf->nsamp;
332  starttime = wf->starttime;
333  endtime = wf->endtime;
334  samprate = wf->samprate;
335  if (samprate < 0.01)
336  {
337    logit("et", "unreasonable samplerate (%f) for <%s.%s.%s.%s>\n",
338          samprate, wf->sta, wf->chan, wf->net, wf->loc);
339    return( EW_FAILURE );
340  }
341  begintime = starttime;
342  datatype = 'n';
343  if (wf->datatype[0] == 's' || wf->datatype[0] == 'i')
344  {
345    if (wf->datatype[1] == '2') datatype = 's';
346    else if (wf->datatype[1] == '4') datatype = 'l';
347  }
348  else if (wf->datatype[0] == 't' || wf->datatype[0] == 'f')
349  {
350    if (wf->datatype[1] == '4') datatype = 'f';
351  }
352  if (datatype == 'n')
353  {
354    logit("et", "SUDSPA_next: unsupported datatype: %c\n", datatype);
355    return( EW_FAILURE );
356  }
357
358  if (debug == 1)
359    logit("et", "SUDSPA_next: working on <%s/%s/%s/%s> datatype: %c \n",
360                        wf->sta, wf->chan, wf->net,wf->loc, datatype);
361
362  /* loop through all the messages for this s-c-n */
363  while (1) 
364  {
365    /* advance message pointer to the data */
366    msg_p += sizeof(TRACE2_HEADER);
367       
368    /* check for sufficient memory in output buffer */
369    this_size = (nsamp_this_scn + nsamp ) * sizeof(int32_t);
370    if ( OutBufferLen < this_size )
371    {
372      logit( "e", "out of space for <%s.%s.%s.%s>; saving long trace.\n",
373             wf->sta, wf->chan, wf->net, wf->loc);
374      break;
375    }
376 
377        /* if data are floats, clip to longs cjb 5/18/2001 */
378    switch( datatype )
379    {
380    case 's':
381      s_data = (short *)msg_p;
382      for ( j = 0; j < nsamp ; j++, nsamp_this_scn++ )
383        SudsBuffer[nsamp_this_scn] = (int32_t) s_data[j];
384      msg_p += sizeof(short) * nsamp;
385      break;
386    case 'l':
387      l_data = (int32_t *)msg_p;
388      for ( j = 0; j < nsamp; j++, nsamp_this_scn++ )
389          SudsBuffer[nsamp_this_scn] = l_data[j];
390      msg_p += sizeof(int32_t) * nsamp;
391      break;
392    case 'f':
393      /* CLIP the data to 32-bit int */
394      for ( j = 0; j < nsamp; j++, nsamp_this_scn++ )
395      {
396        if (l_data[j] < (float)INT32_MIN)
397          SudsBuffer[nsamp_this_scn] = INT32_MIN;
398        else if (l_data[j] > (float) INT32_MAX)
399          SudsBuffer[nsamp_this_scn] = INT32_MAX;
400        else
401          SudsBuffer[nsamp_this_scn] = (int32_t) l_data[j];
402      }
403      msg_p += sizeof(float) * nsamp;
404      break;
405    }
406 
407    /* End-check based on length of snippet buffer */
408    if ((size_t) msg_p >= ((size_t) getThis->actLen + (size_t) getThis->pBuf))
409    {
410      if (debug == 1)
411        logit ("", "Setting done for <%s.%s.%s.%s>\n", wf->sta, wf->chan, 
412               wf->net, wf->loc);
413      break; /* Break out of the while(1) loop 'cuz we're done */
414    }
415 
416    /* msg_p has been advanced to the next TRACE_BUF; localize bytes *
417     * and check for gaps.                                           */
418    wf = (TRACE2_HEADER *) msg_p;
419    if (WaveMsg2MakeLocal(wf) < 0)
420    {
421      logit("e", "SUDSPA_next: unknown trace data type: %s\n",
422            wf->datatype);
423      return( EW_FAILURE );
424    }
425    nsamp = wf->nsamp;
426    starttime = wf->starttime; 
427    /* starttime is set for new packet; endtime is still set for old packet */
428    if ( endtime + ( 1.0/samprate ) * GapThresh < starttime ) 
429    {
430      /* there's a gap, so fill it */
431      logit("e", "gap in %s.%s.%s.%s: %lf: %lf\n", wf->sta, wf->chan, wf->net,
432            wf->loc, endtime, starttime - endtime);
433      nfill = (long) (samprate * (starttime - endtime) - 1);
434      if ( (nsamp_this_scn + nfill) * (long)sizeof(int32_t) > OutBufferLen )
435      {
436        logit("e", 
437              "bogus gap (%ld); skipping\n", nfill);
438        return(EW_FAILURE);
439      }
440      /* do the filling */
441      for ( j = 0; j < nfill; j++, nsamp_this_scn ++ ) 
442        SudsBuffer[nsamp_this_scn] = fill;
443      /* keep track of how many gaps and the largest one */
444      gap_count++;
445      if (nfill_max < nfill) 
446        nfill_max = nfill;
447    }
448    /* Advance endtime to the new packet;        *
449     * process this packet in the next iteration */
450    endtime = wf->endtime;
451  } /* while(1) */
452     
453  /* figure out min, max, and "noise" */
454  for (j = 0; j < 200 && j < nsamp_this_scn; j++)
455  {
456    if (SudsBuffer[j] > max)
457      max = SudsBuffer[j];
458    if (SudsBuffer[j] < min)
459      min = SudsBuffer[j];
460    total += SudsBuffer[j];
461  }
462  dt.avenoise = ((float)total)/ (float)j;  /* Mean of the first 200 samples */
463  for (; j < nsamp_this_scn; j++)
464  {
465    if (SudsBuffer[j] > max)
466      max = SudsBuffer[j];
467    if (SudsBuffer[j] < min)
468      min = SudsBuffer[j];
469  }
470
471  /* If the incoming data were originally short integers, copy the values
472     back to an array of shorts; disk space saving feature requested
473         by Gabriel Reyes cjb 6/11/01 */
474  if (datatype == 's') 
475  {
476    for (j = 0; j < nsamp_this_scn; j++)
477                SudsBufferShort[j] = (short)SudsBuffer[j];
478  }
479
480  /* Convert to the appropriate output format */
481#if defined (_INTEL)
482  /* we are on intel, data will be read on sparc */
483  if (strcmp (SudsOutputFormat, "sparc") == 0)
484    for (j = 0; j < nsamp_this_scn; j++)
485    {
486                if (datatype == 's')
487                        SwapShort(&SudsBufferShort[j]);
488                else
489                        SwapInt32(&SudsBuffer[j]);
490        }
491#elif defined (_SPARC)
492  /* we are on sparc, data will be read on intel */
493  if (strcmp (SudsOutputFormat, "intel") == 0)
494    for (j = 0; j < nsamp_this_scn; j++)
495    {
496                if (datatype == 's')
497                        SwapShort(&SudsBufferShort[j]);
498                else
499                        SwapInt32(&SudsBuffer[j]);
500        }
501#else
502  logit ("e", "SUDSPA_next: Can't determine my platform - please compile with either _INTEL or _SPARC set\n");
503      return EW_FAILURE;
504#endif
505               
506  /* Write out to the SUDS file */
507  /* Fill and write TAG for the STATIONCOMP struct */
508
509  tag.id_struct = STATIONCOMP; /* what follows is STATIONCOMP */
510  tag.len_struct = sizeof (SUDS_STATIONCOMP); 
511  tag.len_data = 0;
512  tag.sync = 'S';
513
514  if (debug == 1)
515    logit ("", "Writing tag for %d (%d)\n", tag.id_struct, tag.len_struct);
516
517  if (strcmp (SudsOutputFormat, "sparc") == 0)
518    tag.machine = '1';
519  else if (strcmp (SudsOutputFormat, "intel") == 0)
520    tag.machine = '6';
521
522  if (StructMakeLocal ((void *) &tag, STRUCTTAG, tag.machine, debug) 
523      != EW_SUCCESS)
524  {
525    logit ("et", "SUDSPA_next: Call to StructMakeLocal failed. \n");
526    return EW_FAILURE;
527  }
528
529  if (fwrite ((void *) &tag, sizeof (SUDS_STRUCTTAG), 1, SUDSfp) != 1)
530  {
531    logit ("et", "SUDSPA_next: error writing SUDS tag. \n");
532    return EW_FAILURE;
533  }
534
535  /* Fill and write STATIONCOMP struct */
536  /* Where do we put SEED location code? */
537  /* in SUDS_STATIDENT structure, char st_name[5],
538        char network[4], char component where component = v,n,e
539        cjb 5/18/2001 */
540  if (strlen(wf->sta) > 5) {
541        strncpy(sc.sc_name.st_name, wf->sta, 4);
542        sc.sc_name.st_name[4] = '\0';
543  }
544  else
545        strcpy (sc.sc_name.st_name, wf->sta); 
546
547 if (strlen(wf->net) > 4) {
548        strncpy(sc.sc_name.network, wf->net, 3);
549        sc.sc_name.network[3] = '\0';
550  }
551  else
552        strcpy (sc.sc_name.network, wf->net); 
553
554  if (strlen(wf->chan) >= 3)
555        sc.sc_name.component = wf->chan[2];
556  else 
557        sc.sc_name.component = wf->chan[0];
558
559  if ((sc.sc_name.component == 'Z') || (sc.sc_name.component == 'z'))
560          sc.sc_name.component = 'V';
561
562  if ((sc.sc_name.component != 'N') && (sc.sc_name.component != 'n')
563          && (sc.sc_name.component != 'E') && (sc.sc_name.component != 'e')
564          && (sc.sc_name.component != 'V') && (sc.sc_name.component != 'v')
565          && (sc.sc_name.component != 'T') && (sc.sc_name.component != 't'))
566          logit("et", "SUDSPA_next: unknown station component %c \n",
567                sc.sc_name.component);
568
569  if (datatype == 's')
570        sc.data_type = 's';
571  else
572          sc.data_type = 'l';
573  sc.data_units = 'd';
574
575  if (debug == 1)
576    logit ("", "Writing STATIONCOMP struct for %s.%s.%c\n", 
577           sc.sc_name.st_name,
578           sc.sc_name.network,     
579           sc.sc_name.component);
580
581  if (StructMakeLocal ((void *) &sc, STATIONCOMP, tag.machine, debug) 
582      != EW_SUCCESS)
583  {
584    logit ("et", "SUDSPA_next: Call to StructMakeLocal failed. \n");
585    return EW_FAILURE;
586  }
587
588  if (fwrite ((void *) &sc, sizeof (SUDS_STATIONCOMP), 1, SUDSfp) != 1)
589  {
590    logit ("et", "SUDSPA_next: error writing SUDS_STATIONCOMP struct. \n");
591    return EW_FAILURE;
592  }
593
594  /* Fill and write TAG for the DESCRIPTRACE struct */
595  if (datatype == 's')
596        data_size = nsamp_this_scn * sizeof (short);
597  else
598        data_size = nsamp_this_scn * sizeof (int32_t);
599  tag.id_struct = DESCRIPTRACE; /* what follows is DESCRIPTRACE */
600  tag.len_struct = sizeof (SUDS_DESCRIPTRACE); 
601  tag.len_data = (int32_t) data_size;
602
603  if (debug == 1)
604    logit ("", "Writing tag for %d (%d)\n", tag.id_struct, tag.len_struct);
605
606  if (StructMakeLocal ((void *) &tag, STRUCTTAG, tag.machine, debug) != EW_SUCCESS)
607  {
608    logit ("et", "SUDSPA_next: Call to StructMakeLocal failed. \n");
609    return EW_FAILURE;
610  }
611
612  if (fwrite ((void *) &tag, sizeof (SUDS_STRUCTTAG), 1, SUDSfp) != 1)
613  {
614    logit ("et", "SUDSPA_next: error writing SUDS tag. \n");
615    return EW_FAILURE;
616  }
617
618  /* Fill and write DESCRIPTRACE struct */
619  /*strcpy (dt.dt_name.st_name, wf->sta);
620  strcpy (dt.dt_name.network, wf->net);
621  dt.dt_name.component = wf->chan[0];
622  */
623  /* in SUDS_STATIDENT structure, char st_name[5],
624        char network[4], char component where component = v,n,e
625        cjb 5/18/2001 */
626  if (strlen(wf->sta) > 5) {
627        strncpy(dt.dt_name.st_name, wf->sta, 4);
628        dt.dt_name.st_name[4] = '\0';
629  }
630  else
631        strcpy (dt.dt_name.st_name, wf->sta); 
632
633 if (strlen(wf->net) > 4) {
634        strncpy(dt.dt_name.network, wf->net, 3);
635        dt.dt_name.network[3] = '\0';
636  }
637  else
638        strcpy (dt.dt_name.network, wf->net); 
639
640  if (strlen(wf->chan) >= 3)
641    dt.dt_name.component = wf->chan[2];
642  else 
643    dt.dt_name.component = wf->chan[0];
644
645  if ((dt.dt_name.component == 'Z') || (dt.dt_name.component == 'z'))
646          dt.dt_name.component = 'V';
647
648  if ((dt.dt_name.component != 'N') && (dt.dt_name.component != 'n')
649          && (dt.dt_name.component != 'E') && (dt.dt_name.component != 'e')
650          && (dt.dt_name.component != 'V') && (dt.dt_name.component != 'v')
651          && (dt.dt_name.component != 'T') && (dt.dt_name.component != 't'))
652          logit("et", "SUDSPA_next: error with station component %c \n",
653                dt.dt_name.component);
654  /* Where do we put SEED location code? */
655
656  if (datatype == 's')
657          dt.datatype = 's';
658  else
659          dt.datatype = 'l';
660  dt.begintime = begintime;
661  dt.length = nsamp_this_scn;
662  dt.rate = (float) wf->samprate;
663  dt.mindata = (float) min;
664  dt.maxdata = (float) max;
665
666  /* Ignore the rest for now - see how it works */
667
668  if (debug == 1)
669    logit ("", "Writing DESCRIPTRACE - %ld samples (%ld,%ld) \n", 
670           nsamp_this_scn, min, max);
671
672  if (StructMakeLocal ((void *) &dt, DESCRIPTRACE, tag.machine, debug) != EW_SUCCESS)
673  {
674    logit ("et", "SUDSPA_next: Call to StructMakeLocal failed. \n");
675    return EW_FAILURE;
676  }
677
678  if (fwrite ((void *) &dt, sizeof (SUDS_DESCRIPTRACE), 1, SUDSfp) != 1)
679  {
680    logit ("et", "SUDSPA_next: error writing DESCRIPTRACE struct. \n");
681    return EW_FAILURE;
682  }
683
684  /* write TRACE data - SudsBuffer holds long data;
685          SudsBufferShort holds short data */
686  if (debug == 1)
687    logit ("", "Writing %d bytes of DESCRIPTRACE data\n", data_size);
688  if (datatype == 's')
689  {
690        if ((int)fwrite ((void *) SudsBufferShort, sizeof (char), data_size, SUDSfp)
691                != data_size)
692        {
693                logit ("et", "SUDSPA_next: error writing short TRACE data. \n");
694                return EW_FAILURE;
695        }
696  }
697  else
698  {
699        if ((int)fwrite ((void *) SudsBuffer, sizeof (char), data_size, SUDSfp)
700                != data_size)
701        {
702                logit ("et", "SUDSPA_next: error writing long TRACE data. \n");
703                return EW_FAILURE;
704        }
705  }
706  return EW_SUCCESS;
707}
708
709
710/************************************************************************
711* This is the Put Away end event routine. It's called after we've       *
712* finished processing one event                                         *
713*                                                                       *
714* For PC-SUDS - close the SUDS file, pointed to by SUDSfp               *
715*               free SudsBuffer memory to be nice to everyone else      *
716*************************************************************************/
717int SUDSPA_end_ev(int debug)
718{
719  fclose (SUDSfp);
720       
721  if (debug == 1)
722    logit("t", "Closing SUDS file \n");
723
724  return( EW_SUCCESS );
725}
726
727
728/************************************************************************
729*       This is the Put Away close routine. It's called after when      *
730*       we're being shut down.                                          *
731*************************************************************************/
732int SUDSPA_close(int debug)
733{
734
735  free ((char *) SudsBufferShort);
736  free ((char *) SudsBuffer);
737  return( EW_SUCCESS );
738}
739
740
741/*
742 *
743 *  Byte swapping functions
744 */
745
746/* swap bytes if necessary, depending on what machine */
747/* we have been compiled, and what machine the data   */
748/* is being read from/being written to                */
749
750static int StructMakeLocal(void *ptr, int struct_type, char data_type, 
751                           int debug)
752{
753  if (ptr == NULL)
754  {
755    logit ("e", "StructMakeLocal: NULL pointer passed in\n");
756    return EW_FAILURE;
757  }
758
759#if defined (_INTEL)
760  if (data_type != '6')
761  {
762    if (debug == 1)
763      logit ("", "Swapping from Intel to Sun \n");
764
765    /* if we are on intel, and target data is not intel */
766    if (SwapDo (ptr, struct_type) != EW_SUCCESS)
767    {
768      logit ("e", "StructMakeLocal: Call to SwapDo failed \n");
769      return EW_FAILURE;
770    }
771  }
772
773#elif defined (_SPARC)
774  if (data_type == '6')
775  {
776    if (debug == 1)
777      logit ("", "Swapping from Sun to Intel \n");
778
779    /* if we are on solaris, and target data is not solaris */
780    if (SwapDo (ptr, struct_type) != EW_SUCCESS)
781    {
782      logit ("e", "StructMakeLocal: Call to SwapDo failed \n");
783      return EW_FAILURE;
784    }
785  }
786
787#endif
788  return EW_SUCCESS;
789}
790
791
792/* Do the dirty work by swapping the innards of SUDS */
793/* structures that are of interest to us             */
794static int SwapDo( void *ptr, int struct_type)
795{
796  SUDS_STRUCTTAG *tag;
797  SUDS_STATIONCOMP *sc;
798  SUDS_DESCRIPTRACE *dt;
799  SUDS_TRIGGERS *tr;
800  SUDS_DETECTOR *de;
801  SUDS_TIMECORRECTION *tc;
802
803  if (ptr == NULL)
804  {
805    logit ("e", "SwapDo: NULL pointer passed in.\n");
806    return EW_FAILURE;
807  }
808
809  switch( struct_type ) 
810  {
811  case STRUCTTAG:
812    tag = (SUDS_STRUCTTAG *) ptr;
813    SwapShort (&tag->id_struct);
814    SwapInt32 (&tag->len_struct);
815    SwapInt32 (&tag->len_data);
816    break;
817  case STATIONCOMP:
818    sc = (SUDS_STATIONCOMP *) ptr;
819    SwapShort (&sc->sc_name.inst_type);
820    SwapShort (&sc->azim);
821    SwapShort (&sc->incid);
822    SwapDouble (&sc->st_lat);
823    SwapDouble (&sc->st_long);
824    SwapFloat (&sc->elev);
825    SwapShort (&sc->rocktype);
826    SwapFloat (&sc->max_gain);
827    SwapFloat (&sc->clip_value);
828    SwapFloat (&sc->con_mvolts);
829    SwapShort (&sc->channel);
830    SwapShort (&sc->atod_gain);
831    SwapInt32 (&sc->effective);
832    SwapFloat (&sc->clock_correct);
833    SwapFloat (&sc->station_delay);
834    break;
835  case DESCRIPTRACE:
836    dt = (SUDS_DESCRIPTRACE *) ptr;
837    SwapShort (&dt->dt_name.inst_type);
838    SwapDouble (&dt->begintime);
839    SwapShort (&dt->localtime);
840    SwapShort (&dt->digi_by);
841    SwapShort (&dt->processed);
842    SwapInt32 (&dt->length);
843    SwapFloat (&dt->rate);
844    SwapFloat (&dt->mindata);
845    SwapFloat (&dt->maxdata);
846    SwapFloat (&dt->avenoise);
847    SwapInt32 (&dt->numclip);
848    SwapDouble (&dt->time_correct);
849    SwapFloat (&dt->rate_correct);
850    break;
851  case TRIGGERS:
852    tr = (SUDS_TRIGGERS *) ptr;
853    SwapShort (&tr->tr_name.inst_type);
854    SwapShort (&tr->sta);
855    SwapShort (&tr->lta);
856    SwapShort (&tr->abs_sta);
857    SwapShort (&tr->abs_lta);
858    SwapShort (&tr->trig_value);
859    SwapShort (&tr->num_triggers);
860    SwapDouble (&tr->trig_time);
861    break;
862  case DETECTOR:
863    de = (SUDS_DETECTOR *) ptr;
864    SwapFloat (&de->versionnum);
865    SwapInt32 (&de->event_number);
866    SwapInt32 (&de->spareL);
867    break;
868  case TIMECORRECTION:
869    tc = (SUDS_TIMECORRECTION *) ptr;
870    SwapShort (&tc->tm_name.inst_type);
871    SwapDouble (&tc->time_correct);
872    SwapFloat (&tc->rate_correct);
873#ifdef WIN64
874    {    /* special handing to address alignment issues with 64-bit Windows */
875      int32_t tmpval = tc->effective_time;
876      SwapInt32 (&tmpval);
877      tc->effective_time = tmpval;
878    }
879#else
880    SwapInt32 (&tc->effective_time);
881#endif
882    SwapShort (&tc->spareM);
883    break;
884  default:
885    logit ("e", "SwapDo: Don't know about type %d\n", struct_type);
886    return EW_FAILURE;
887  }
888
889  return EW_SUCCESS;
890}
Note: See TracBrowser for help on using the repository browser.