source: trunk/src/archiving/ew2mseed/ew2mseed_utils.c @ 7519

Revision 7519, 19.3 KB checked in by baker, 5 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/*=====================================================================
2// Copyright (C) 2000,2001 Instrumental Software Technologies, Inc.
3//
4// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions
6// are met:
7// 1. Redistributions of source code, or portions of this source code,
8//    must retain the above copyright notice, this list of conditions
9//    and the following disclaimer.
10// 2. Redistributions in binary form must reproduce the above copyright
11//    notice, this list of conditions and the following disclaimer in
12//    the documentation and/or other materials provided with the
13//    distribution.
14// 3. All advertising materials mentioning features or use of this
15//    software must display the following acknowledgment:
16//    "This product includes software developed by Instrumental
17//    Software Technologies, Inc. (http://www.isti.com)"
18// 4. If the software is provided with, or as part of a commercial
19//    product, or is used in other commercial software products the
20//    customer must be informed that "This product includes software
21//    developed by Instrumental Software Technologies, Inc.
22//    (http://www.isti.com)"
23// 5. The names "Instrumental Software Technologies, Inc." and "ISTI"
24//    must not be used to endorse or promote products derived from
25//    this software without prior written permission. For written
26//    permission, please contact "info@isti.com".
27// 6. Products derived from this software may not be called "ISTI"
28//    nor may "ISTI" appear in their names without prior written
29//    permission of Instrumental Software Technologies, Inc.
30// 7. Redistributions of any form whatsoever must retain the following
31//    acknowledgment:
32//    "This product includes software developed by Instrumental
33//    Software Technologies, Inc. (http://www.isti.com/)."
34// THIS SOFTWARE IS PROVIDED BY INSTRUMENTAL SOFTWARE
35// TECHNOLOGIES, INC. "AS IS" AND ANY EXPRESSED OR IMPLIED
36// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
37// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
38// DISCLAIMED.  IN NO EVENT SHALL INSTRUMENTAL SOFTWARE TECHNOLOGIES,
39// INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
40// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
41// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
42// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
43// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
44// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
45// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
46// OF THE POSSIBILITY OF SUCH DAMAGE.
47//=====================================================================
48//  A current version of the software can be found at
49//                http://www.isti.com
50//  Bug reports and comments should be directed to
51//  Instrumental Software Technologies, Inc. at info@isti.com
52//=====================================================================
53// This work was funded by the IRIS Data Management Center
54// http://www.iris.washington.edu
55//=====================================================================
56*/
57/*
58**   THIS FILE IS UNDER RCS - DO NOT MODIFY UNLESS YOU HAVE
59**   CHECKED IT OUT USING THE COMMAND CHECKOUT.
60**
61**    $Id$
62**
63**      Revision history:
64**      $Log$
65**      Revision 1.1  2010/03/10 17:14:58  paulf
66**      first check in of ew2mseed to EW proper
67**
68**      Revision 1.5  2007/04/13 19:43:22  hal
69**      use flock instead of lockf when compiling under cygwin (which lacks lockf)
70**     
71**      Revision 1.4  2007/04/12 19:21:04  hal
72**      Added ew7.0+ support (-dSUPPORT_SCNL) and linux port (-D_LINUX)
73**     
74**      -Hal
75**     
76**      Revision 1.3  2002/12/19 00:35:00  ilya
77**      Byteswapping in shorts and doubles is fixed
78**     
79**      Revision 1.2  2002/04/02 14:42:01  ilya
80**      Version 02-Apr-2002: catchup algorithm
81**     
82**      Revision 1.1.1.1  2002/01/24 18:32:05  ilya
83**      Exporting only ew2mseed!
84**     
85**      Revision 1.1.1.1  2001/11/20 21:47:00  ilya
86**      First CVS commit
87**     
88 * Revision 1.7  2001/03/15  16:42:52  comserv
89 *      void signal_handler() modified to accomodate SIGALRM
90 *
91 * Revision 1.6  2001/02/06  17:19:32  comserv
92 * Functions logFailedSCN() resetWsTrace() are moved to ew2mseed_utils.c
93 * Functions  logFailedSCN() and  checkLock() are changed, so you can actually
94 * write data into them, and still use them for locking. int lockfd is now a global
95 * variable
96 *
97 * Revision 1.5  2001/02/06  05:53:29  comserv
98 * Added code  to make sure is that the content of the lockfile is truncated to zero.
99 * We now write SCNs which we cannot process in this file
100 *
101 * Revision 1.4  2001/01/18  21:58:20  comserv
102 * checkForGaps is modified to detect snippet overlaps
103 *
104 * Revision 1.4  2001/01/18  21:58:20  comserv
105 * checkForGaps is modified to detect snippet overlaps
106 *
107 * Revision 1.3  2001/01/17  21:56:54  comserv
108 * prerelease version ; copyright statement
109 *
110 * Revision 1.2  2001/01/08  22:55:31  comserv
111 * locking function is added
112 *
113 * Revision 1.1  2000/11/17  06:56:57  comserv
114 * Initial revision
115 *
116*/
117
118/* Standard includes */
119#include <stdio.h>
120#include <string.h>
121#include <stdlib.h>
122#include <errno.h>
123#include <sys/types.h>
124#include <sys/stat.h>
125#include <dirent.h>
126#include <signal.h>
127#include <unistd.h>
128#include <fcntl.h>
129#include <math.h>
130
131#ifdef _CYGWIN
132#  include <sys/file.h>
133#endif
134
135/* Includes from Earthworm distribution */
136#include "earthworm.h"
137
138/* Local includes */
139#include "ew2mseed.h"
140#include "swap.h"
141#include "qlib2.h"
142
143/* Global variable */
144int lockfd = -1;
145
146/***************************************************************************/
147  double getReqEndTime (double startTime, double SampRate, int samples)
148  {
149        double endTime;
150        endTime = startTime + (double)samples/SampRate;
151        return endTime; 
152  }
153
154
155/*****************************************************************************/
156/* Define how many UNCOMPRESSED bytes from WS we have to request to fill     */
157/* for sure a single MiniSEED record                                         */ 
158/* IGD 03/28/02 highWaterMark is assuming possible increase in the size of   */
159/* the requested snippet                                                     */
160/****************************************************************************/
161  long int assumeSnippetSize (int logRec, short CompAlg, short RecNum, 
162                int highWaterMark)
163  { 
164        long int bytes;
165       
166        /*Must be larger than the maximum */
167        if (CompAlg == STEIM1)
168                bytes = 2 * logRec * RecNum * highWaterMark * sizeof(int);
169        else if(CompAlg == STEIM2)
170                bytes = 4 * logRec * RecNum * highWaterMark * sizeof(int);
171        else    {
172                fprintf(stderr, "fatal error in assumeSnippetSize: %d is not supported compression algorithm\n", CompAlg);
173                logit("pt", "fatal error in assumeSnippetSize: %d is not supported compression algorithm\n", CompAlg);
174                return -1;
175                }
176        return bytes;
177  }
178
179/***************************************************************************/
180
181  void makeSNCLoop (RINGS *rn)
182  {
183        int i; 
184        struct SCN_ring *scn_head;
185
186        scn_head = rn->scnRing; 
187
188        for (i=0; i < rn->SCN_avail-1; i++)
189                rn->scnRing = rn->scnRing->next;
190       
191        rn->scnRing->next = scn_head;   
192
193
194  } 
195/***************************************************************************/
196/************************************************************************/
197/*  checkForGaps:                                                       */
198/*      Reads in the sampling rate, time of the last sample of the      */ 
199/*      previous snippet and the first sample of the current snippet.   */
200/*      Checks for the data consistency                                 */
201/*  returns:                                                            */
202/*      0 if there is no gaps (tears) or overlaps                       */
203/*      positive double gap in seconds or negative overlap in seconds   */
204/*                                                                      */
205/************************************************************************/ 
206  double checkForGaps (double prevEndTime, double startTime, double sampRate)
207  {
208        double smallValue, invSampRate;
209
210        invSampRate = 1./sampRate;
211        smallValue = invSampRate/10.;
212
213        /* Here is the gap
214         ****************************/ 
215        if ((prevEndTime + invSampRate + smallValue) < startTime )
216                return (startTime - prevEndTime - invSampRate);  /*positive */
217
218        /* Here is the overlap
219         ***************************/
220        if ((prevEndTime + invSampRate - smallValue) > startTime )
221                return (startTime - prevEndTime - invSampRate); /* negative */
222
223        return 0;
224  }
225/****************************************************************************/
226  long ew2mseedAddData (int *buffer, char *msg_p, long position, int bufLen, char swap, int bytesPerSample)
227  {     float *fBuf = NULL;
228        int *iBuf = NULL;
229        short *sBuf= NULL;
230        int i;
231
232        if (swap == 't' && bytesPerSample == 8) /*t8 SUN IEEE double precision real */
233        {
234                for (i = 0; i< bufLen; i ++)
235                {
236                        double tmp;
237                        tmp = *(sBuf + i);
238#if defined _INTEL
239                        ew2mseed_SwapDouble(&tmp, 't'); 
240#endif
241                        *(buffer + i+ position) = (int)tmp;     
242                }
243        }       
244        else if (swap == 't' && bytesPerSample == 4) /*t4 SUN IEEE single precision real */
245        {
246                fBuf = (float *) msg_p;
247                for (i = 0; i< bufLen; i ++)
248                {
249                        *(buffer + i+ position) = (int) *(fBuf + i);
250#if defined _INTEL
251                        SwapInt(buffer+i+position);
252#endif 
253                }       
254        }
255        else if (swap == 's' && bytesPerSample == 4) /*s4 SUN IEEE integer */
256        {
257                iBuf = (int *) msg_p;
258                for (i = 0; i< bufLen; i ++)
259                {
260                        *(buffer + i+ position) = (int) *(iBuf + i);
261#if defined _INTEL
262                        SwapInt(buffer+i+position);
263#endif
264                }               
265        }
266        else if (swap == 's' && bytesPerSample == 2) /*s2 SUN IEEE short integer */
267        {       
268                sBuf = (short *) msg_p;
269                for (i = 0; i< bufLen; i ++)
270                {
271                        short tmp;
272                        tmp = *(sBuf + i);
273#if defined _INTEL
274                        ew2mseed_SwapShort(&tmp, 's');
275#endif 
276                        *(buffer + i+ position) = (int) tmp;
277                }
278        }
279        else if (swap == 'f' && bytesPerSample == 8) /*f8 VAX/Intel IEEE double precision real */
280        {
281                for (i = 0; i< bufLen; i ++)
282                {
283                        double tmp;
284                        tmp = *(sBuf + i);
285#if defined _SPARC
286                        ew2mseed_SwapDouble(&tmp, 'f');
287#endif 
288                        *(buffer + i+ position) = (int) tmp;
289                }       
290        }
291        else if (swap == 'f' && bytesPerSample == 4) /*f4 VAX/Intel IEEE single precision real */
292        {
293                fBuf = (float *) msg_p;
294                for (i = 0; i< bufLen; i ++)
295                {
296                        *(buffer + i+ position) = (int) *(fBuf + i);
297#if defined _SPARC
298                        SwapInt(buffer+i+position);
299#endif         
300                }
301        }
302        else if (swap == 'i' && bytesPerSample == 4) /*i4 VAX/Intel IEEE integer */
303        {
304                iBuf = (int *) msg_p;
305                for (i = 0; i< bufLen; i ++)
306                {
307                        *(buffer + i+ position) = (int) *(iBuf + i);
308#if defined _SPARC
309                        SwapInt(buffer+i+position);
310#endif
311                }               
312        }
313        else if (swap == 'i' && bytesPerSample == 2) /*i2 VAX/Intel IEEE short integer */       
314        {
315                sBuf = (short *) msg_p;
316                for (i = 0; i< bufLen; i ++)
317                {
318                        short tmp;
319                        tmp = *(sBuf + i);
320#if defined _SPARC
321                        ew2mseed_SwapShort(&tmp, 'i');
322#endif 
323                        *(buffer + i+ position) = (int) tmp; 
324                }               
325        }
326        else
327        {
328                return -1;
329        }
330
331        return (position + bufLen);
332  }
333
334/****************************************************************************/
335  int getBufferShift (double reqStarttime, double actStarttime, double samprate)
336  {
337        int myshift;
338        double timeDiff;
339        double verySmall = 0.000001;
340
341        if (reqStarttime < actStarttime)
342        {
343                if (reqStarttime + 0.5/samprate >= actStarttime )
344                        return 0;       
345                else
346                        return -1;
347        }
348
349        timeDiff = reqStarttime - actStarttime;
350        myshift = (int) nearbyint(timeDiff * samprate);
351        while (1)
352        {
353                if ( actStarttime + myshift/samprate - reqStarttime >= (0.5/samprate))
354                {
355                        if (fabs(actStarttime + myshift/samprate - reqStarttime - 0.5/samprate) < verySmall )
356                        {
357                                printf("fabs = %f\n", fabs(actStarttime + myshift/samprate - reqStarttime - 0.5/samprate));
358                                break;
359                        }
360                        myshift--;
361                }
362                else if (actStarttime + myshift/samprate - reqStarttime < -0.5/samprate)
363                {
364                        myshift++;
365                }
366                else
367                        break;
368        }       
369/*      printf("%d %f %f %f\n", myshift, actStarttime + myshift/samprate - reqStarttime, samprate,  timeDiff); */
370        return myshift;
371       
372  } 
373
374/****************************************************************************/
375
376  int checkCompilationFlags (char *prog)
377  {     int retVal = -2;
378#ifdef _SPARC
379        retVal = 1;
380#endif
381#ifdef  _INTEL
382        retVal = 1;
383#endif
384        if(retVal == -2)
385        {
386        fprintf(stderr, "-------------------------------------------------------\n");
387        fprintf(stderr, "%s should be compiled with -D_SPARC or -D_INTEL flags only!\n", prog);
388        fprintf(stderr, "Please recompile the program with this flag\n");
389        fprintf(stderr, "-------------------------------------------------------\n");
390        }
391
392        return(retVal);
393  }
394
395  char *strDate( double epochTime, char *dd)
396  {
397        /* Warning: dd should be allocated outside ! */
398
399
400        /* SEC1970 is a convertion from epoch to julian seconds */
401        date20(epochTime + SEC1970, dd);
402        return dd;
403  }
404
405/**********************************************************/
406
407  double findNewFileJulTime (double jtime)
408  {     
409        double nextDayJtime;
410        EXT_TIME ext_time;
411 
412        ext_time = int_to_ext (tepoch_to_int(jtime));
413        ext_time.hour = 0;
414        ext_time.minute = 0;
415        ext_time.second = 0;
416        ext_time.usec = 0;
417        /* next day */
418        nextDayJtime = int_to_tepoch(ext_to_int(ext_time)) + 24 * 60 *60;
419        return (nextDayJtime);
420 }
421  /* IGD 03/14/01 Modified for SIGALRM and
422   *********************************/
423  void signal_handler (int sig)
424  {
425        if (sig == SIGUSR1)     
426                ew_signal_flag = EW2MSEED_MAKE_REPORT; 
427        else if (sig == SIGALRM)
428                ew_signal_flag = EW2MSEED_ALARM; 
429        else
430                ew_signal_flag = EW2MSEED_TERMINATE;
431        signal(sig, signal_handler); /*Re-install handler */   
432  }
433
434  void finish_handler (RINGS *rn)
435  {
436        fprintf(stderr, "TERMINATION SIGNAL ARRIVED\n");
437        fprintf(stderr, "PROGRAM EXITS NOW\n");
438        logit("pt", "TERMINATION SIGNAL ARRIVED\n");
439        logit("pt", "PROGRAM EXITS NOW\n");
440        ew_signal_flag = EW2MSEED_OK;
441        exit(0);       
442  }
443 
444  void ew2mseedGenReport (RINGS *p_rn)
445  {
446
447
448        fprintf(stderr, "STATE-OF-HEALTH REPORT REQUEST RECEIVED\n");
449        ew2mseed_logconfig(p_rn);
450
451        fprintf(stderr, "REPORT IS WRITTEN INTO THE LOG FILE\n");
452        ew_signal_flag = EW2MSEED_OK;
453       
454       
455  }
456
457  int checkLock (char * lockfile)
458  {
459        int status;
460        if (lockfile == NULL)
461        {
462                fprintf(stderr, "This instance of ew2mseed does not use the locking mechanism!\n");
463                fprintf(stderr, "Multiple copies of ew2mseed are allowed to write into a single data file\n");
464                fprintf(stderr, "To enable locking set LockFile parameter in the configuration file\n");
465                logit ("", "This instance of ew2mseed does not use the locking mechanism!\n");
466                logit("", "Multiple copies of ew2mseed are allowed to write into a single data file\n");
467                logit("", "To enable locking set LockFile parameter in the configuration file\n");
468                return(0);
469        }
470
471        if ((lockfd = open (lockfile, O_RDWR|O_CREAT,0644)) < 0) 
472        {
473                fprintf (stderr, "Error in ew2mseed: Unable to open lockfile: %s\n", lockfile);
474                logit ("pt", "Error in ew2mseed: Unable to open lockfile: %s\n", lockfile);
475                return (-1);
476        }       
477#ifdef _CYGWIN
478        if ((status=flock(lockfd, LOCK_EX|LOCK_NB)) < 0)
479#else
480        if ((status=lockf (lockfd, F_TLOCK, 0)) < 0)
481#endif
482        {
483                fprintf (stderr, "Error in ew2mseed: Unable to lock lockfile: %s status=%d errno=%d\n", 
484                                lockfile, status, errno);
485                logit ("pt", "Error in ew2mseed Unable to lock daemon lockfile: %s status=%d errno=%d\n", 
486                                lockfile, status, errno);
487                return(-2);
488        }
489        close(lockfd);
490       
491        if ((lockfd = open (lockfile, O_RDWR|O_CREAT|O_TRUNC,0644)) < 0) 
492        {
493                fprintf (stderr, "Error in ew2mseed: Unable to open lockfile: %s\n", lockfile);
494                logit ("pt", "Error in ew2mseed: Unable to open lockfile: %s\n", lockfile);
495                return (-1);
496        }
497
498#ifdef _CYGWIN
499        if ((status=flock(lockfd, LOCK_EX|LOCK_NB)) < 0)
500#else
501        if ((status=lockf (lockfd, F_TLOCK, 0)) < 0)
502#endif
503        {
504                fprintf (stderr, "Error in ew2mseed: Unable to lock lockfile: %s status=%d errno=%d\n", 
505                                lockfile, status, errno);
506                logit ("pt", "Error in ew2mseed Unable to lock daemon lockfile: %s status=%d errno=%d\n", 
507                                lockfile, status, errno);
508                return(-2);
509        }
510        return(1); /*Success */
511       
512  }
513/*---------------------------------------------------------*/
514/* IGD 02/05/01 a function to reset TRACE_REQ * strucuture */
515
516        int resetWsTrace (TRACE_REQ* trace, double startTime, double endTime)
517        {
518                trace->bufLen = 0;
519                trace->reqStarttime = startTime;
520                trace->reqEndtime = endTime;
521                free(trace->pBuf);
522                trace->pBuf = (char *)NULL;
523                trace->timeout = 0;
524                trace->actStarttime = 0;
525                trace->actEndtime = 0;
526                trace->actLen = 0;
527                trace->retFlag = 0;
528                return 0;
529        }
530
531/* IGD this function is added on 02/05/01 */
532
533        void logFailedSCN (struct SCN_ring *failedTrace, char *lockFN) 
534        {
535               
536                char line[100];
537                char locId[5];
538                char alg[7];
539                memset(&locId[0], '\0', 5);
540                if (failedTrace->locId[0] == '\000')
541                        strcpy(locId, "NONE");
542                else
543                        strncpy(locId, failedTrace->locId, 2); 
544                if (failedTrace->CompAlg == 11)
545                        strcpy(alg, "STEIM2");
546                else if  (failedTrace->CompAlg == 10)
547                        strcpy(alg, "STEIM1");
548                else
549                        strcpy(alg, "ALG???");
550                sprintf(line, "SCNLocSZ %s %s %s %s %d %s\n",
551                        failedTrace->traceRec.sta, failedTrace->traceRec.chan,
552                        failedTrace->traceRec.net, locId, failedTrace->logRec, alg);
553
554                logit("pt", "Trace %s is removed from ew2mseed loop\n", line);
555
556                if (lockfd == -1 )
557                        fprintf(stderr,  "Trace %s is removed from ew2mseed loop\n", line);
558                else   
559                        write(lockfd, line, strlen(line));
560                return;
561        }
562
563 
564/* IGD 03/29/02 Computes priority for catchup algorithm */
565       
566void  updatePriorityValues(RINGS *rn)
567{
568 struct SCN_ring *scn_head;
569 int i; 
570 int j = 0;
571 double meanSystemTime = 0;
572 double timeFromTank = 0;       
573 int priorityFactor = 3600 * 24; /* 1 day */
574 int priority;
575 int TankPriority;
576 int previous_priority;
577               
578        /* Get the ring start */
579        scn_head = rn->scnRing;
580
581        for (i = 0; i< rn->SCN_avail; i++)     
582        {
583                /* Process uninitialized cases */
584                if (rn->scnRing->prevStarttime <= 0 ||
585                        rn->scnRing->prevEndtime <= 0)
586                {
587                        rn->scnRing->lastRequestTime = -1;
588                } 
589                else /* Normal cases */
590                {
591                        rn->scnRing->lastRequestTime =
592                                        rn->scnRing->prevEndtime;
593                        meanSystemTime += rn->scnRing->lastRequestTime;
594                        j++;
595                }
596                rn->scnRing = rn->scnRing->next;
597        }
598       
599        meanSystemTime /= j;
600
601        /* distribute priorities */
602        for (i = 0; i< rn->SCN_avail; i++)     
603        {       
604                /* See how far away we are from tank start */
605                timeFromTank = rn->scnRing->lastRequestTime -
606                        rn->scnRing->tankStarttime;
607                if (timeFromTank < 900) /* 15 mins */
608                        TankPriority = rn->PriorityHighWater;
609                else if (timeFromTank < 1800)
610                        TankPriority = rn->PriorityHighWater/2;
611                else 
612                        TankPriority = 1;
613
614                previous_priority = rn->scnRing->priority;
615
616                priority = (meanSystemTime - rn->scnRing->lastRequestTime) /
617                                priorityFactor;
618                if (TankPriority > priority)
619                        priority = TankPriority;
620 
621                if (priority < 0)
622                        rn->scnRing->priority  = 1;
623                else if (priority > rn->PriorityHighWater)
624                        rn->scnRing->priority = rn->PriorityHighWater;
625                else
626                        rn->scnRing->priority = priority;
627
628                rn->scnRing->timeInterval = rn->scnRing->timeInterval / previous_priority * rn->scnRing->priority;     
629
630                if (rn->verbosity > 3)
631                {
632                        logit("pt", "           SCN-%d   = %7s %7s %7s %7s : priority (%1d) %10.1f secs later than mean\n",
633                                i, rn->scnRing->traceRec.sta, 
634                                rn->scnRing->traceRec.chan, 
635                                rn->scnRing->traceRec.net,
636                                rn->scnRing->locId, 
637                                rn->scnRing->priority,
638                                meanSystemTime - rn->scnRing->lastRequestTime);
639
640                        logit("pt", "           SCN-%d   = %7s %7s %7s %7s:  time interval is set to %f s\n",
641                                i, rn->scnRing->traceRec.sta, 
642                                rn->scnRing->traceRec.chan, 
643                                rn->scnRing->traceRec.net,
644                                rn->scnRing->locId, 
645                                rn->scnRing->timeInterval);
646
647                }       
648                rn->scnRing = rn->scnRing->next;
649
650       
651        }
652
653        /* Set back the start of the ring */
654        rn->scnRing = scn_head;
655
656        return;
657}
Note: See TracBrowser for help on using the repository browser.