Main Page Class Hierarchy Compound List File List Compound Members File Members

# sudsputaway.c

Go to the documentation of this file.

    00001 /*
    00002  *   THIS FILE IS UNDER RCS - DO NOT MODIFY UNLESS YOU HAVE
    00003  *   CHECKED IT OUT USING THE COMMAND CHECKOUT.
    00004  *
    00005  *    $Id: sudsputaway_8c-source.html,v 1.1 2006/05/19 16:55:02 paulf Exp $
    00006  *
    00007  *    Revision history:
    00008  *     $Log: sudsputaway_8c-source.html,v $
    00008  *     Revision 1.1  2006/05/19 16:55:02  paulf
    00008  *     first inclusion
    00008  *
    00009  *     Revision 1.9  2002/01/08 17:02:29  cjbryan
    00010  *     In order to accommodate 24-bit broadband data, traces of data of longer than long are now clipped to +/-2147483648
    00011  *
    00012  *     Revision 1.8  2001/04/12 03:47:36  lombard
    00013  *     Major reorganization of SUDSPA_next to improve efficiency
    00014  *     Reformatted code; cleaned up lots of comments and logit calls
    00015  *     Removed mapping of NC component codes (only needed at UW)
    00016  *     Now traces of data larger than short in are clipped to +/- 32767
    00017  *     counts; before they were byte-truncated.
    00018  *     Initializes SUDS structures to zero before filling them.
    00019  *
    00020  *     Revision 1.7  2001/03/27 22:22:51  cjbryan
    00021  *     ensured that time portion of suds format is hhmmss and not hhmmss.ss as carried by EventTime variable
    00022  *
    00023  *     Revision 1.6  2001/03/22 20:55:12  cjbryan
    00024  *     deleted now obsolete EventInst variable
    00025  *
    00026  *     Revision 1.5  2001/03/21 23:15:23  cjbryan
    00027  *     integrated CVO subnet into output filename
    00028  *
    00029  *     Revision 1.4  2001/03/21 16:41:07  alex
    00030  *     added EventSubnet variable to carry subnet name through to
    00031  *     filename; deleted now extraneous EventMod variable
    00032  *
    00033  *     Revision 1.3  2001/03/21 02:23:03  alex
    00034  *     *** empty log message ***
    00035  *
    00036  *     Revision 1.2  2000/03/10 23:23:43  davidk
    00037  *     changed the sudsputaway routines to match the new PA_XXX
    00038  *     routines in putaway.c.
    00039  *     Moved the SUDSPA_XXX function prototypes to pa_other_head.h
    00040  *
    00041  *     Revision 1.1  2000/02/14 18:51:48  lucky
    00042  *     Initial revision
    00043  *
    00044  *
    00045  */
    00046
    00047 /* sudsputaway.c
    00048
    00049         Routines for writing trace data in PC-SUDS format
    00050
    00051
    00052   Thu Jul 22 14:56:37 MDT 1999 Lucky Vidmar
    00053     Major structural changes to accomodate making all putaway routines
    00054     into library calls so that they can be shared between trig2disk
    00055     and wave2disk. Eliminated global variables set and allocated outside
    00056     of this file. We should only have static globals from now on, with
    00057     everything else being passed in via the putaway.c calls.
    00058 */
    00059
    00060 #include <limits.h>
    00061 #include <stdio.h>
    00062 #include <stdlib.h>
    00063 #include <string.h>
    00064 #include <errno.h>
    00065 #include <earthworm.h>
    00066 #include <time.h>
    00067 #include <trace_buf.h>
    00068 #include <swap.h>
    00069 #include <ws_clientII.h>
    00070 #include <sudshead.h>
    00071 #include <pa_subs.h>
    00072
    00073 #define TAG_FILE        '.tag'        /* file containing the last known file tag */
    00074 #define MAXTXT           150
    00075
    00076
    00077 FILE    *SUDSfp;                      /* file pointer for the SUDS file */
    00078
    00079 static  long   *SudsBuffer;           /* write out SUDS data as long integers */
    00080 static  short  *SudsBufferShort;      /* write out SUDS data as short integers */
    00081 static  char SudsOutputFormat[MAXTXT];
    00082
    00083 /* Internal Function Prototypes */
    00084 static int StructMakeLocal (void *, int, char, int);
    00085 static int SwapDo (void *, int);
    00086
    00087 /************************************************************************
    00088 * Initialization function,                                              *
    00089 *       This is the Put Away startup intializer. This is called when    *
    00090 *       the system first comes up. Here is a chance to look around      *
    00091 *       and see if it's possible to do business, and to complain        *
    00092 *       if not ,BEFORE an event has to be processed.                    *
    00093 *                                                                       *
    00094 *       For PCSUDS, all we want to do is to make sure that the          *
    00095 *       directory where files should be written exists.                 *
    00096 *************************************************************************/
    00097 int SUDSPA_init (int OutBufferLen, char *OutDir, char *OutputFormat,
    00098                  int debug)
    00099 {
    00107   if ((SudsBuffer = (long *) malloc (OutBufferLen * sizeof (char))) == NULL)
    00108   {
    00109     logit ("et", "SUDSPA_init: couldn't malloc SudsBuffer\n");
    00110     return EW_FAILURE;
    00111   }
    00112   if ((SudsBufferShort = (short *) malloc (OutBufferLen * sizeof (char))) == NULL)
    00113   {
    00114     logit ("et", "SUDSPA_init: couldn't malloc SudsBufferShort\n");
    00115     return EW_FAILURE;
    00116   }
    00117
    00118   /* Make sure that the top level output directory exists */
    00119   if (CreateDir (OutDir) != EW_SUCCESS)
    00120   {
    00121     logit ("e", "SUDSPA_init: Call to CreateDir failed\n");
    00122     return EW_FAILURE;
    00123   }
    00124
    00125   if(strlen(OutputFormat) >= sizeof(SudsOutputFormat))
    00126   {
    00127     logit("","SUDSPA_init: Error: OutputFormat(%s) is too long! Quitting!\n",
    00128           OutputFormat);
    00129     return(EW_FAILURE);
    00130   }
    00131   else
    00132   {
    00133     strcpy(SudsOutputFormat,OutputFormat);
    00134   }
    00135   return EW_SUCCESS;
    00136 }
    00137
    00138 /************************************************************************
    00139 *   This is the Put Away event initializer. It's called when a snippet  *
    00140 *   has been received, and is about to be processed.                    *
    00141 *   It gets to see the pointer to the TraceRequest array,               *
    00142 *   and the number of loaded trace structures.                          *
    00143 *                                                                       *
    00144 *   For PCSUDS, we need to make sure that the target directory          *
    00145 *   exists, create it if it does not, then open the SUDS file           *
    00146 *   for writing.                                                        *
    00147 *************************************************************************/
    00148 int SUDSPA_next_ev (char *EventID, TRACE_REQ *ptrReq, int nReq,
    00149                     char *OutDir, char *EventDate, char *EventTime,
    00150                     char *EventSubnet, int debug)
    00151
    00152 {
    00153   char    SUDSFile[4*MAXTXT];
    00154   char    hhmmss[7];
    00155
    00156   /* Changed by Eugene Lublinsky, 3/31/Y2K */
    00157   /* There are 2 modes of behavior now: the default one when insmod */
    00158   /* is numeric or the second one when insmod is alphanumeric */
    00159   char  tmpEventID[EVENTID_SIZE + 3];
    00160
    00161   /* We treat suds file slightly differently - by request
    00162    * from Tom Murray. The files are placed directly into the
    00163    * top level suds directory, with names as follows:
    00164    *
    00165    *    yyyymmdd_hhmmss_insmod_evid.dmx
    00166    */
    00167
    00168   /* Changed by Eugene Lublinsky, 3/31/Y2K */
    00169   /* choose which way to go */
    00170
    00171   /* Build the file name */
    00172   /* added by murray (and it shows) to set the eventid at 3 characters */
    00173   if (strlen(EventID) < 3)
    00174     sprintf (tmpEventID,"000%s",EventID) ;
    00175   else
    00176     sprintf (tmpEventID,"%s",EventID) ;
    00177
    00178   /* ensure that time string is of the form hhmmss (revised EventTime
    00179      allows a string of the form hhmmss.ss, so truncate it if necessary) */
    00180   if (strlen(EventTime) > 6)
    00181   {
    00182     strncpy(hhmmss, EventTime, 6);
    00183     hhmmss[6] = '\0';
    00184   }
    00185   else
    00186     strcpy(hhmmss, EventTime);
    00187
    00188   /* changed by Carol 3/21/01: if no subnet, use network name
    00189      in filename */
    00190   if (EventSubnet[0] != '\0')
    00191     sprintf (SUDSFile, "%s/%s_%s_%s_%s.dmx", OutDir,
    00192              EventDate, hhmmss, EventSubnet,
    00193              &tmpEventID[strlen(tmpEventID)-3]);
    00194   else
    00195     sprintf (SUDSFile, "%s/%s_%s_%s_%s.dmx", OutDir,
    00196              EventDate, hhmmss, ptrReq->net,
    00197              &tmpEventID[strlen(tmpEventID)-3]);
    00198
    00199   /* end of changes */
    00200
    00201   if (debug == 1)
    00202     logit ("t", "Opening SUDS file %s\n", SUDSFile);
    00203
    00204   /* open file */
    00205   if ((SUDSfp = fopen (SUDSFile, "wb")) == NULL)
    00206   {
    00207     logit ("e", "SUDSPA_next_ev: unable to open file %s: %s\n",
    00208            SUDSFile, strerror(errno));
    00209     return EW_FAILURE;
    00210   }
    00211
    00212   return (EW_SUCCESS);
    00213 }
    00214
    00215 /************************************************************************
    00216 * This is the working entry point into the disposal system. This        *
    00217 * routine gets called for each trace snippet which has been recovered.  *
    00218 * It gets to see the corresponding SNIPPET structure, and the event id  *
    00219 *                                                                       *
    00220 * For PCSUDS, this routine writes to the SUDS file, pointed to by the   *
    00221 * SUDSfp pointer, all of the received trace data in SUDS format:        *
    00222 *                                                                       *
    00223 *      1. SUDS tag - indicating what follows                            *
    00224 *      2. SUDS_STATIONCOMP struct - describe the station                *
    00225 *      3. SUDS tag - indicating what follows                            *
    00226 *      4. SUDS_DESCRIPTRACE struct - describe the trace data            *
    00227 *      5. trace data                                                    *
    00228 *                                                                       *
    00229 *  One bit of complexity is that we need to write the files in the      *
    00230 *  correct byte-order. Based on the OutputFormat parameter, determine   *
    00231 *  whether or not to swap bytes before writing the suds file.           *
    00232 *                                                                       *
    00233 * WARNING: we clip trace data to -2147483648 - +2147483647 so it will   *
    00234 *  fit in a long int. Any incoming data that is longer than 32 bits     *
    00235 *  will be CLIPPED. cjb 5/18/2001                                       *
    00236 *************************************************************************/
    00237 /* Process one channel of data */
    00238 int SUDSPA_next (TRACE_REQ *getThis, double GapThresh,
    00239                  long OutBufferLen, int debug)
    00240 {
    00241   TRACE_HEADER *wf;
    00242   short  *s_data;
    00243   long   *l_data;
    00244   float  *f_data;
    00245   char   *msg_p;        /* pointer into tracebuf data */
    00246   char    datatype;
    00247   int     data_size;
    00248   int     j;
    00249   int     gap_count = 0;
    00250   long    nsamp, nfill;
    00251   long    nfill_max = 0l;
    00252   long    nsamp_this_scn = 0l;
    00253   long    this_size;
    00254   double  begintime, starttime, endtime;
    00255   double  samprate;
    00256   long    fill = 0l;
    00257   long    min, max;
    00258   int     total;
    00259   SUDS_STRUCTTAG          tag;
    00260   SUDS_DESCRIPTRACE       dt;
    00261   SUDS_STATIONCOMP        sc;
    00262
    00263   /* Check arguments */
    00264   if (getThis == NULL)
    00265   {
    00266     logit ("e", "SUDSPA_next: invalid argument passed in.\n");
    00267     return EW_FAILURE;
    00268   }
    00269
    00270   /* Start with a clean slate */
    00271   memset(&tag, 0, sizeof(tag));
    00272   memset(&dt, 0, sizeof(dt));
    00273   memset(&sc, 0, sizeof(sc));
    00274
    00275   /* Used for computing trace statistics */
    00276   max = 4096;
    00277   min = 0;
    00278   total = 0;
    00279
    00280   if ( (msg_p = getThis->pBuf) == NULL)   /* pointer to first message */
    00281   {
    00282     logit ("e", "SUDSPA_next: Message buffer is NULL.\n");
    00283     return EW_FAILURE;
    00284   }
    00285   wf = (TRACE_HEADER *) msg_p;
    00286
    00287   /* Look at the first TRACE_HEADER and get set up of action */
    00288   if (WaveMsgMakeLocal(wf) < 0)
    00289   {
    00290     logit("e", "SUDSPA_next: unknown trace data type: %s\n",
    00291           wf->datatype);
    00292     return( EW_FAILURE );
    00293   }
    00294
    00295   nsamp = wf->nsamp;
    00296   starttime = wf->starttime;
    00297   endtime = wf->endtime;
    00298   samprate = wf->samprate;
    00299   if (samprate < 0.01)
    00300   {
    00301     logit("et", "unreasonable samplerate (%f) for <%s.%s.%s>\n",
    00302           samprate, wf->sta, wf->chan, wf->net);
    00303     return( EW_FAILURE );
    00304   }
    00305   begintime = starttime;
    00306   datatype = 'n';
    00307   if (wf->datatype[0] == 's' || wf->datatype[0] == 'i')
    00308   {
    00309     if (wf->datatype[1] == '2') datatype = 's';
    00310     else if (wf->datatype[1] == '4') datatype = 'l';
    00311   }
    00312   else if (wf->datatype[0] == 't' || wf->datatype[0] == 'f')
    00313   {
    00314     if (wf->datatype[1] == '4') datatype = 'f';
    00315   }
    00316   if (datatype == 'n')
    00317   {
    00318     logit("et", "SUDSPA_next: unsupported datatype: %s\n", datatype);
    00319     return( EW_FAILURE );
    00320   }
    00321
    00322   if (debug == 1)
    00323     logit("et", "SUDSPA_next: working on <%s/%s/%s> datatype: %c \n",
    00324                         wf->sta, wf->chan, wf->net, datatype);
    00325
    00326   /* loop through all the messages for this s-c-n */
    00327   while (1)
    00328   {
    00329     /* advance message pointer to the data */
    00330     msg_p += sizeof(TRACE_HEADER);
    00331
    00332     /* check for sufficient memory in output buffer */
    00333     this_size = (nsamp_this_scn + nsamp ) * sizeof(long);
    00334     if ( OutBufferLen < this_size )
    00335     {
    00336       logit( "e", "out of space for <%s.%s.%s>; saving long trace.\n",
    00337              wf->sta, wf->chan, wf->net);
    00338       break;
    00339     }
    00340
    00341         /* if data are floats, clip to longs cjb 5/18/2001 */
    00342     switch( datatype )
    00343     {
    00344     case 's':
    00345       s_data = (short *)msg_p;
    00346       for ( j = 0; j < nsamp ; j++, nsamp_this_scn++ )
    00347         SudsBuffer[nsamp_this_scn] = (long) s_data[j];
    00348       msg_p += sizeof(short) * nsamp;
    00349       break;
    00350     case 'l':
    00351       l_data = (long *)msg_p;
    00352       for ( j = 0; j < nsamp; j++, nsamp_this_scn++ )
    00353           SudsBuffer[nsamp_this_scn] = l_data[j];
    00354       msg_p += sizeof(long) * nsamp;
    00355       break;
    00356     case 'f':
    00357       f_data = (float *)msg_p;
    00358       /* CLIP the data to long int */
    00359       for ( j = 0; j < nsamp; j++, nsamp_this_scn++ )
    00360       {
    00361         if (l_data[j] < (float)LONG_MIN)
    00362           SudsBuffer[nsamp_this_scn] = LONG_MIN;
    00363         else if (l_data[j] > (float) LONG_MAX)
    00364           SudsBuffer[nsamp_this_scn] = LONG_MAX;
    00365         else
    00366           SudsBuffer[nsamp_this_scn] = (long) l_data[j];
    00367       }
    00368       msg_p += sizeof(float) * nsamp;
    00369       break;
    00370     }
    00371
    00372     /* End-check based on length of snippet buffer */
    00373     if ((long) msg_p >= ((long) getThis->actLen + (long) getThis->pBuf))
    00374     {
    00375       if (debug == 1)
    00376         logit ("", "Setting done for <%s.%s.%s>\n", wf->sta, wf->chan,
    00377                wf->net);
    00378       break; /* Break out of the while(1) loop 'cuz we're done */
    00379     }
    00380
    00381     /* msg_p has been advanced to the next TRACE_BUF; localize bytes *
    00382      * and check for gaps.                                           */
    00383     wf = (TRACE_HEADER *) msg_p;
    00384     if (WaveMsgMakeLocal(wf) < 0)
    00385     {
    00386       logit("e", "SUDSPA_next: unknown trace data type: %s\n",
    00387             wf->datatype);
    00388       return( EW_FAILURE );
    00389     }
    00390     nsamp = wf->nsamp;
    00391     starttime = wf->starttime;
    00392     /* starttime is set for new packet; endtime is still set for old packet */
    00393     if ( endtime + ( 1.0/samprate ) * GapThresh < starttime )
    00394     {
    00395       /* there's a gap, so fill it */
    00396       logit("e", "gap in %s.%s.%s: %lf: %lf\n", wf->sta, wf->chan, wf->net,
    00397             endtime, starttime - endtime);
    00398       nfill = (long) (samprate * (starttime - endtime) - 1);
    00399       if ( (nsamp_this_scn + nfill) * (long)sizeof(long) > OutBufferLen )
    00400       {
    00401         logit("e",
    00402               "bogus gap (%d); skipping\n", nfill);
    00403         return(EW_FAILURE);
    00404       }
    00405       /* do the filling */
    00406       for ( j = 0; j < nfill; j++, nsamp_this_scn ++ )
    00407         SudsBuffer[nsamp_this_scn] = fill;
    00408       /* keep track of how many gaps and the largest one */
    00409       gap_count++;
    00410       if (nfill_max < nfill)
    00411         nfill_max = nfill;
    00412     }
    00413     /* Advance endtime to the new packet;        *
    00414      * process this packet in the next iteration */
    00415     endtime = wf->endtime;
    00416   } /* while(1) */
    00417
    00418   /* figure out min, max, and "noise" */
    00419   for (j = 0; j < 200 && j < nsamp_this_scn; j++)
    00420   {
    00421     if (SudsBuffer[j] > max)
    00422       max = SudsBuffer[j];
    00423     if (SudsBuffer[j] < min)
    00424       min = SudsBuffer[j];
    00425     total += SudsBuffer[j];
    00426   }
    00427   dt.avenoise = ((float)total)/ (float)j;  /* Mean of the first 200 samples */
    00428   for (; j < nsamp_this_scn; j++)
    00429   {
    00430     if (SudsBuffer[j] > max)
    00431       max = SudsBuffer[j];
    00432     if (SudsBuffer[j] < min)
    00433       min = SudsBuffer[j];
    00434   }
    00435
    00436   /* If the incoming data were originally short integers, copy the values
    00437      back to an array of shorts; disk space saving feature requested
    00438          by Gabriel Reyes cjb 6/11/01 */
    00439   if (datatype == 's')
    00440   {
    00441     for (j = 0; j < nsamp_this_scn; j++)
    00442                 SudsBufferShort[j] = (short)SudsBuffer[j];
    00443   }
    00444
    00445   /* Convert to the appropriate output format */
    00446 #if defined (_INTEL)
    00447   /* we are on intel, data will be read on sparc */
    00448   if (strcmp (SudsOutputFormat, "sparc") == 0)
    00449     for (j = 0; j < nsamp_this_scn; j++)
    00450     {
    00451                 if (datatype == 's')
    00452                         SwapShort(&SudsBufferShort[j]);
    00453                 else
    00454                         SwapLong(&SudsBuffer[j]);
    00455         }
    00456 #elif defined (_SPARC)
    00457   /* we are on sparc, data will be read on intel */
    00458   if (strcmp (SudsOutputFormat, "intel") == 0)
    00459     for (j = 0; j < nsamp_this_scn; j++)
    00460     {
    00461                 if (datatype == 's')
    00462                         SwapShort(&SudsBufferShort[j]);
    00463                 else
    00464                         SwapLong(&SudsBuffer[j]);
    00465         }
    00466 #else
    00467   logit ("e", "SUDSPA_next: Can't determine my platform - please compile with either _INTEL or _SPARC set\n");
    00468       return EW_FAILURE;
    00469 #endif
    00470
    00471   /* Write out to the SUDS file */
    00472   /* Fill and write TAG for the STATIONCOMP struct */
    00473
    00474   tag.id_struct = STATIONCOMP; /* what follows is STATIONCOMP */
    00475   tag.len_struct = sizeof (SUDS_STATIONCOMP);
    00476   tag.len_data = 0;
    00477   tag.sync = 'S';
    00478
    00479   if (debug == 1)
    00480     logit ("", "Writing tag for %d (%d)\n", tag.id_struct, tag.len_struct);
    00481
    00482   if (strcmp (SudsOutputFormat, "sparc") == 0)
    00483     tag.machine = '1';
    00484   else if (strcmp (SudsOutputFormat, "intel") == 0)
    00485     tag.machine = '6';
    00486
    00487   if (StructMakeLocal ((void *) &tag, STRUCTTAG, tag.machine, debug)
    00488       != EW_SUCCESS)
    00489   {
    00490     logit ("et", "SUDSPA_next: Call to StructMakeLocal failed. \n");
    00491     return EW_FAILURE;
    00492   }
    00493
    00494   if (fwrite ((void *) &tag, sizeof (SUDS_STRUCTTAG), 1, SUDSfp) != 1)
    00495   {
    00496     logit ("et", "SUDSPA_next: error writing SUDS tag. \n");
    00497     return EW_FAILURE;
    00498   }
    00499
    00500   /* Fill and write STATIONCOMP struct */
    00501   /* in SUDS_STATIDENT structure, char st_name[5],
    00502         char network[4], char component where component = v,n,e
    00503         cjb 5/18/2001 */
    00504   if (strlen(wf->sta) > 5) {
    00505         strncpy(sc.sc_name.st_name, wf->sta, 4);
    00506         sc.sc_name.st_name[4] = '\0';
    00507   }
    00508   else
    00509         strcpy (sc.sc_name.st_name, wf->sta);
    00510
    00511  if (strlen(wf->net) > 4) {
    00512         strncpy(sc.sc_name.network, wf->net, 3);
    00513         sc.sc_name.network[3] = '\0';
    00514   }
    00515   else
    00516         strcpy (sc.sc_name.network, wf->net);
    00517
    00518   if (strlen(wf->chan) >= 3)
    00519         sc.sc_name.component = wf->chan[2];
    00520   else
    00521         sc.sc_name.component = wf->chan[0];
    00522
    00523   if ((sc.sc_name.component == 'Z') || (sc.sc_name.component == 'z'))
    00524           sc.sc_name.component = 'V';
    00525
    00526   if ((sc.sc_name.component != 'N') && (sc.sc_name.component != 'n')
    00527           && (sc.sc_name.component != 'E') && (sc.sc_name.component != 'e')
    00528           && (sc.sc_name.component != 'V') && (sc.sc_name.component != 'v')
    00529           && (sc.sc_name.component != 'T') && (sc.sc_name.component != 't'))
    00530           logit("et", "SUDSPA_next: unknown station component %c \n",
    00531                 sc.sc_name.component);
    00532
    00533   if (datatype == 's')
    00534         sc.data_type = 's';
    00535   else
    00536           sc.data_type = 'l';
    00537   sc.data_units = 'd';
    00538
    00539   if (debug == 1)
    00540     logit ("", "Writing STATIONCOMP struct for %s.%s.%c\n",
    00541            sc.sc_name.st_name,
    00542            sc.sc_name.network,
    00543            sc.sc_name.component);
    00544
    00545   if (StructMakeLocal ((void *) &sc, STATIONCOMP, tag.machine, debug)
    00546       != EW_SUCCESS)
    00547   {
    00548     logit ("et", "SUDSPA_next: Call to StructMakeLocal failed. \n");
    00549     return EW_FAILURE;
    00550   }
    00551
    00552   if (fwrite ((void *) &sc, sizeof (SUDS_STATIONCOMP), 1, SUDSfp) != 1)
    00553   {
    00554     logit ("et", "SUDSPA_next: error writing SUDS_STATIONCOMP struct. \n");
    00555     return EW_FAILURE;
    00556   }
    00557
    00558   /* Fill and write TAG for the DESCRIPTRACE struct */
    00559   if (datatype == 's')
    00560         data_size = nsamp_this_scn * sizeof (short);
    00561   else
    00562         data_size = nsamp_this_scn * sizeof (long);
    00563   tag.id_struct = DESCRIPTRACE; /* what follows is DESCRIPTRACE */
    00564   tag.len_struct = sizeof (SUDS_DESCRIPTRACE);
    00565   tag.len_data = (long) data_size;
    00566
    00567   if (debug == 1)
    00568     logit ("", "Writing tag for %d (%d)\n", tag.id_struct, tag.len_struct);
    00569
    00570   if (StructMakeLocal ((void *) &tag, STRUCTTAG, tag.machine, debug) != EW_SUCCESS)
    00571   {
    00572     logit ("et", "SUDSPA_next: Call to StructMakeLocal failed. \n");
    00573     return EW_FAILURE;
    00574   }
    00575
    00576   if (fwrite ((void *) &tag, sizeof (SUDS_STRUCTTAG), 1, SUDSfp) != 1)
    00577   {
    00578     logit ("et", "SUDSPA_next: error writing SUDS tag. \n");
    00579     return EW_FAILURE;
    00580   }
    00581
    00582   /* Fill and write DESCRIPTRACE struct */
    00583   /*strcpy (dt.dt_name.st_name, wf->sta);
    00584   strcpy (dt.dt_name.network, wf->net);
    00585   dt.dt_name.component = wf->chan[0];
    00586   */
    00587   /* in SUDS_STATIDENT structure, char st_name[5],
    00588         char network[4], char component where component = v,n,e
    00589         cjb 5/18/2001 */
    00590   if (strlen(wf->sta) > 5) {
    00591         strncpy(dt.dt_name.st_name, wf->sta, 4);
    00592         dt.dt_name.st_name[4] = '\0';
    00593   }
    00594   else
    00595         strcpy (dt.dt_name.st_name, wf->sta);
    00596
    00597  if (strlen(wf->net) > 4) {
    00598         strncpy(dt.dt_name.network, wf->net, 3);
    00599         dt.dt_name.network[3] = '\0';
    00600   }
    00601   else
    00602         strcpy (dt.dt_name.network, wf->net);
    00603
    00604   if (strlen(wf->chan) >= 3)
    00605     dt.dt_name.component = wf->chan[2];
    00606   else
    00607     dt.dt_name.component = wf->chan[0];
    00608
    00609   if ((dt.dt_name.component == 'Z') || (dt.dt_name.component == 'z'))
    00610           dt.dt_name.component = 'V';
    00611
    00612   if ((dt.dt_name.component != 'N') && (dt.dt_name.component != 'n')
    00613           && (dt.dt_name.component != 'E') && (dt.dt_name.component != 'e')
    00614           && (dt.dt_name.component != 'V') && (dt.dt_name.component != 'v')
    00615           && (dt.dt_name.component != 'T') && (dt.dt_name.component != 't'))
    00616           logit("et", "SUDSPA_next: error with station component %c \n",
    00617                 dt.dt_name.component);
    00618
    00619
    00620   if (datatype == 's')
    00621           dt.datatype = 's';
    00622   else
    00623           dt.datatype = 'l';
    00624   dt.begintime = begintime;
    00625   dt.length = nsamp_this_scn;
    00626   dt.rate = (float) wf->samprate;
    00627   dt.mindata = (float) min;
    00628   dt.maxdata = (float) max;
    00629
    00630   /* Ignore the rest for now - see how it works */
    00631
    00632   if (debug == 1)
    00633     logit ("", "Writing DESCRIPTRACE - %d samples (%d,%d) \n",
    00634            nsamp_this_scn, min, max);
    00635
    00636   if (StructMakeLocal ((void *) &dt, DESCRIPTRACE, tag.machine, debug) != EW_SUCCESS)
    00637   {
    00638     logit ("et", "SUDSPA_next: Call to StructMakeLocal failed. \n");
    00639     return EW_FAILURE;
    00640   }
    00641
    00642   if (fwrite ((void *) &dt, sizeof (SUDS_DESCRIPTRACE), 1, SUDSfp) != 1)
    00643   {
    00644     logit ("et", "SUDSPA_next: error writing DESCRIPTRACE struct. \n");
    00645     return EW_FAILURE;
    00646   }
    00647
    00648   /* write TRACE data - SudsBuffer holds long data;
    00649           SudsBufferShort holds short data */
    00650   if (debug == 1)
    00651     logit ("", "Writing %d bytes of DESCRIPTRACE data\n", data_size);
    00652   if (datatype == 's')
    00653   {
    00654         if ((long)fwrite ((void *) SudsBufferShort, sizeof (char), data_size, SUDSfp)
    00655                 != data_size)
    00656         {
    00657                 logit ("et", "SUDSPA_next: error writing short TRACE data. \n");
    00658                 return EW_FAILURE;
    00659         }
    00660   }
    00661   else
    00662   {
    00663         if ((long)fwrite ((void *) SudsBuffer, sizeof (char), data_size, SUDSfp)
    00664                 != data_size)
    00665         {
    00666                 logit ("et", "SUDSPA_next: error writing long TRACE data. \n");
    00667                 return EW_FAILURE;
    00668         }
    00669   }
    00670   return EW_SUCCESS;
    00671 }
    00672
    00673
    00674 /************************************************************************
    00675 * This is the Put Away end event routine. It's called after we've       *
    00676 * finished processing one event                                         *
    00677 *                                                                       *
    00678 * For PC-SUDS - close the SUDS file, pointed to by SUDSfp               *
    00679 *               free SudsBuffer memory to be nice to everyone else      *
    00680 *************************************************************************/
    00681 int SUDSPA_end_ev(int debug)
    00682 {
    00683   fclose (SUDSfp);
    00684
    00685   if (debug == 1)
    00686     logit("t", "Closing SUDS file \n");
    00687
    00688   return( EW_SUCCESS );
    00689 }
    00690
    00691
    00692 /************************************************************************
    00693 *       This is the Put Away close routine. It's called after when      *
    00694 *       we're being shut down.                                          *
    00695 *************************************************************************/
    00696 int SUDSPA_close(int debug)
    00697 {
    00698
    00699   free ((char *) SudsBufferShort);
    00700   free ((char *) SudsBuffer);
    00701   return( EW_SUCCESS );
    00702 }
    00703
    00704
    00705 /*
    00706  *
    00707  *  Byte swapping functions
    00708  */
    00709
    00710 /* swap bytes if necessary, depending on what machine */
    00711 /* we have been compiled, and what machine the data   */
    00712 /* is being read from/being written to                */
    00713
    00714 static int StructMakeLocal(void *ptr, int struct_type, char data_type,
    00715                            int debug)
    00716 {
    00717   if (ptr == NULL)
    00718   {
    00719     logit ("e", "StructMakeLocal: NULL pointer passed in\n");
    00720     return EW_FAILURE;
    00721   }
    00722
    00723 #if defined (_INTEL)
    00724   if (data_type != '6')
    00725   {
    00726     if (debug == 1)
    00727       logit ("", "Swapping from Intel to Sun \n");
    00728
    00729     /* if we are on intel, and target data is not intel */
    00730     if (SwapDo (ptr, struct_type) != EW_SUCCESS)
    00731     {
    00732       logit ("e", "StructMakeLocal: Call to SwapDo failed \n");
    00733       return EW_FAILURE;
    00734     }
    00735   }
    00736
    00737 #elif defined (_SPARC)
    00738   if (data_type == '6')
    00739   {
    00740     if (debug == 1)
    00741       logit ("", "Swapping from Sun to Intel \n");
    00742
    00743     /* if we are on solaris, and target data is not solaris */
    00744     if (SwapDo (ptr, struct_type) != EW_SUCCESS)
    00745     {
    00746       logit ("e", "StructMakeLocal: Call to SwapDo failed \n");
    00747       return EW_FAILURE;
    00748     }
    00749   }
    00750
    00751 #endif
    00752   return EW_SUCCESS;
    00753 }
    00754
    00755
    00756 /* Do the dirty work by swapping the innards of SUDS */
    00757 /* structures that are of interest to us             */
    00758 static int SwapDo( void *ptr, int struct_type)
    00759 {
    00760   SUDS_STRUCTTAG *tag;
    00761   SUDS_STATIONCOMP *sc;
    00762   SUDS_DESCRIPTRACE *dt;
    00763   SUDS_TRIGGERS *tr;
    00764   SUDS_DETECTOR *de;
    00765   SUDS_TIMECORRECTION *tc;
    00766
    00767   if (ptr == NULL)
    00768   {
    00769     logit ("e", "SwapDo: NULL pointer passed in.\n");
    00770     return EW_FAILURE;
    00771   }
    00772
    00773   switch( struct_type )
    00774   {
    00775   case STRUCTTAG:
    00776     tag = (SUDS_STRUCTTAG *) ptr;
    00777     SwapShort (&tag->id_struct);
    00778     SwapLong (&tag->len_struct);
    00779     SwapLong (&tag->len_data);
    00780     break;
    00781   case STATIONCOMP:
    00782     sc = (SUDS_STATIONCOMP *) ptr;
    00783     SwapShort (&sc->sc_name.inst_type);
    00784     SwapShort (&sc->azim);
    00785     SwapShort (&sc->incid);
    00786     SwapDouble (&sc->st_lat);
    00787     SwapDouble (&sc->st_long);
    00788     SwapFloat (&sc->elev);
    00789     SwapShort (&sc->rocktype);
    00790     SwapFloat (&sc->max_gain);
    00791     SwapFloat (&sc->clip_value);
    00792     SwapFloat (&sc->con_mvolts);
    00793     SwapShort (&sc->channel);
    00794     SwapShort (&sc->atod_gain);
    00795     SwapLong (&sc->effective);
    00796     SwapFloat (&sc->clock_correct);
    00797     SwapFloat (&sc->station_delay);
    00798     break;
    00799   case DESCRIPTRACE:
    00800     dt = (SUDS_DESCRIPTRACE *) ptr;
    00801     SwapShort (&dt->dt_name.inst_type);
    00802     SwapDouble (&dt->begintime);
    00803     SwapShort (&dt->localtime);
    00804     SwapShort (&dt->digi_by);
    00805     SwapShort (&dt->processed);
    00806     SwapLong (&dt->length);
    00807     SwapFloat (&dt->rate);
    00808     SwapFloat (&dt->mindata);
    00809     SwapFloat (&dt->maxdata);
    00810     SwapFloat (&dt->avenoise);
    00811     SwapLong (&dt->numclip);
    00812     SwapDouble (&dt->time_correct);
    00813     SwapFloat (&dt->rate_correct);
    00814     break;
    00815   case TRIGGERS:
    00816     tr = (SUDS_TRIGGERS *) ptr;
    00817     SwapShort (&tr->tr_name.inst_type);
    00818     SwapShort (&tr->sta);
    00819     SwapShort (&tr->lta);
    00820     SwapShort (&tr->abs_sta);
    00821     SwapShort (&tr->abs_lta);
    00822     SwapShort (&tr->trig_value);
    00823     SwapShort (&tr->num_triggers);
    00824     SwapDouble (&tr->trig_time);
    00825     break;
    00826   case DETECTOR:
    00827     de = (SUDS_DETECTOR *) ptr;
    00828     SwapFloat (&de->versionnum);
    00829     SwapLong (&de->event_number);
    00830     SwapLong (&de->spareL);
    00831     break;
    00832   case TIMECORRECTION:
    00833     tc = (SUDS_TIMECORRECTION *) ptr;
    00834     SwapShort (&tc->tm_name.inst_type);
    00835     SwapDouble (&tc->time_correct);
    00836     SwapFloat (&tc->rate_correct);
    00837     SwapLong (&tc->effective_time);
    00838     SwapShort (&tc->spareM);
    00839     break;
    00840   default:
    00841     logit ("e", "SwapDo: Don't know about type %d\n", struct_type);
    00842     return EW_FAILURE;
    00843   }
    00844
    00845   return EW_SUCCESS;
    00846 }
    00847