1 /*
2  * Argus Software
3  * Copyright (c) 2000-2016 QoSient, LLC
4  * All rights reserved.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2, or (at your option)
9  * any later version.
10 
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15 
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  *
20  */
21 
22 /*
23  * rahisto.c  - histogram tracking.
24  *
25  * written by Carter Bullard
26  * QoSient, LLC
27  *
28  * $Id: //depot/argus/clients/examples/rahisto/rahisto.c#12 $
29  * $DateTime: 2016/06/01 15:17:28 $
30  * $Change: 3148 $
31  */
32 
33 #ifdef HAVE_CONFIG_H
34 #include "argus_config.h"
35 #endif
36 
37 #if defined(CYGWIN)
38 #define USE_IPV6
39 #endif
40 
41 #include <unistd.h>
42 #include <stdlib.h>
43 
44 #include <argus_compat.h>
45 
46 #include <argus_util.h>
47 #include <argus_client.h>
48 #include <argus_main.h>
49 #include <argus_filter.h>
50 
51 #include <rabins.h>
52 #include <rasplit.h>
53 #include <argus_sort.h>
54 #include <argus_cluster.h>
55 
56 #include <signal.h>
57 #include <ctype.h>
58 #include <math.h>
59 
60 struct RaBinProcessStruct *RaBinProcess = NULL;
61 int ArgusProcessOutLayers = 0;
62 int ArgusProcessNoZero = 0;
63 int ArgusPrintInterval = 0;
64 int RaValuesAreIntegers = 1;
65 
66 long long RaNumberOfValues  = 0;
67 long long RaValueBufferSize = 100000;
68 double *RaValueBuffer = NULL;
69 
70 int RaFindModes(double *, long long, double *, int);
71 int RaSortValueBuffer (const void *, const void *);
72 
73 
74 void
ArgusClientInit(struct ArgusParserStruct * parser)75 ArgusClientInit (struct ArgusParserStruct *parser)
76 {
77    struct ArgusModeStruct *mode = NULL;
78    parser->RaWriteOut = 0;
79 
80    if (!(parser->RaInitialized)) {
81 
82       if (parser->Hstr == NULL)
83          usage();
84 
85       (void) signal (SIGHUP,  (void (*)(int)) RaParseComplete);
86       (void) signal (SIGTERM, (void (*)(int)) RaParseComplete);
87       (void) signal (SIGQUIT, (void (*)(int)) RaParseComplete);
88       (void) signal (SIGINT,  (void (*)(int)) RaParseComplete);
89 
90       if ((mode = parser->ArgusModeList) != NULL) {
91          while (mode) {
92             if (!(strncasecmp (mode->mode, "interval", 8)))
93                ArgusPrintInterval = 1;
94             if (!(strncasecmp (mode->mode, "nozero", 6)))
95                ArgusProcessNoZero = 1;
96             if (!(strncasecmp (mode->mode, "outlayer", 8)))
97                ArgusProcessOutLayers = 1;
98 
99             mode = mode->nxt;
100          }
101       }
102 
103       if (ArgusParser->RaPrintOptionStrings[0] == NULL) {
104          int i = 0;
105          while (parser->RaPrintAlgorithmList[i] != NULL) {
106            ArgusFree(parser->RaPrintAlgorithmList[i]);
107            parser->RaPrintAlgorithmList[i] = NULL;
108            i++;
109          }
110       }
111 
112       if ((parser->ArgusAggregator = ArgusNewAggregator(parser, NULL, ARGUS_RECORD_AGGREGATOR)) == NULL)
113          ArgusLog (LOG_ERR, "ArgusClientInit: ArgusNewAggregator error");
114 
115       if (parser->Hstr) {
116          int retn;
117          if (!(retn = ArgusHistoMetricParse (parser, parser->ArgusAggregator)))
118             usage ();
119 
120          switch (retn) {
121             case ARGUS_HISTO_RANGE_UNSPECIFIED: {
122                parser->ArgusPassNum = 2;
123                parser->RaHistoStart =  HUGE_VAL;
124                parser->RaHistoEnd   = -HUGE_VAL;
125                break;
126             }
127 
128             default:
129                parser->RaHistoRangeState |= ARGUS_HISTO_CAPTURE_VALUES;
130                break;
131          }
132       }
133 
134       parser->nflag += 2;
135 
136       if (parser->vflag)
137          ArgusReverseSortDir++;
138 
139       parser->RaInitialized++;
140    }
141 }
142 
143 
RaArgusInputComplete(struct ArgusInput * input)144 void RaArgusInputComplete (struct ArgusInput *input) { return; }
145 
146 
147 void
RaParseComplete(int sig)148 RaParseComplete (int sig)
149 {
150    struct ArgusParserStruct *parser = ArgusParser;
151    struct ArgusRecordStruct *ns = NULL;
152    struct ArgusAgrStruct *tagr = NULL;
153    int i, freq, cum = 0, class = 1, start = 999999999, end = 0;
154    double bs = 0.0, be = 0.0, bf = 0.0;
155    float rel, relcum = 0.0;
156 
157    if (sig >= 0) {
158       if (!parser->RaParseCompleting++) {
159          if (parser->RaHistoRecords) {
160             for (i = 0; i < parser->RaHistoBins + 2; i++) {
161                struct ArgusRecordStruct *argus = parser->RaHistoRecords[i];
162                if ((!ArgusProcessOutLayers && ((i > 0) && (i <= parser->RaHistoBins))) || ArgusProcessOutLayers) {
163                   if (argus) {
164                      if (i < start) start = i;
165                      if (i > end)   end   = i;
166                      if (ns == NULL)
167                         ns = ArgusCopyRecordStruct (argus);
168                      else
169                         ArgusMergeRecords (parser->ArgusAggregator, ns, argus);
170                   }
171                }
172             }
173 
174             if (ns != NULL) {
175                double start, bsize;
176                char buf[MAXSTRLEN];
177                if ((tagr = (void *)ns->dsrs[ARGUS_AGR_INDEX]) != NULL) {
178                   if (parser->ArgusWfileList == NULL) {
179                      int len, tlen, numModes = 0, pflag = parser->pflag;
180                      double modeValues[1024];
181                      double median = 0.0, percentile = 0.0;
182                      char *meanStr = NULL, *medianStr = NULL, *percentStr = NULL;
183                      char *stdStr = NULL, *maxValStr = NULL, *minValStr = NULL;
184                      char *modeStr = NULL;
185                      long long ind;
186                      char c;
187 
188                      sprintf (buf, "%-.*f", pflag, tagr->act.stdev);
189                      stdStr = strdup(buf);
190 
191                      sprintf (buf, "%-.*f", pflag, tagr->act.meanval);
192                      meanStr = strdup(buf);
193 
194                      if (RaValueBuffer != NULL) {
195                         qsort (RaValueBuffer, RaNumberOfValues, sizeof(double), RaSortValueBuffer);
196 
197                         if (RaNumberOfValues % 2) {
198                            median = RaValueBuffer[(RaNumberOfValues + 1)/2];
199 
200                            if (RaValuesAreIntegers)
201                               pflag = 0;
202 
203                         } else {
204                            ind = (RaNumberOfValues / 2) - 1;
205                            median = (RaValueBuffer[ind] + RaValueBuffer[ind + 1]) / 2.0;
206                         }
207 
208                         sprintf (buf, "%-.*f", pflag, median);
209                         medianStr = strdup(buf);
210 
211                         if (RaValuesAreIntegers)
212                            pflag = 0;
213 
214                         ind = RaNumberOfValues * 0.95;
215                         percentile = RaValueBuffer[ind];
216 
217                         sprintf (buf, "%-.*f", pflag, percentile);
218                         percentStr = strdup(buf);
219 
220                         numModes = RaFindModes(RaValueBuffer, RaNumberOfValues, modeValues, 1024);
221 
222                         if (numModes > 0) {
223                            bzero(buf, sizeof(buf));
224                            for (i = 0; i < numModes; i++) {
225                               if (i > 0)
226                                  sprintf(&buf[strlen(buf)], ",");
227 
228                               if (RaValuesAreIntegers)
229                                  sprintf(&buf[strlen(buf)], "%-.0f", modeValues[i]);
230                               else
231                                  sprintf(&buf[strlen(buf)], "%-.*f", pflag, modeValues[i]);
232                            }
233                            modeStr = strdup(buf);
234                         }
235                      }
236 
237                      sprintf (buf, "%-.*f", pflag, tagr->act.maxval);
238                      maxValStr = strdup(buf);
239                      sprintf (buf, "%-.*f", pflag, tagr->act.minval);
240                      minValStr = strdup(buf);
241 
242                      len = strlen(meanStr);
243                      if (medianStr && (len < (tlen = strlen(medianStr))))   len = tlen;
244                      if (percentStr && (len < (tlen = strlen(percentStr)))) len = tlen;
245                      if (stdStr && (len < (tlen = strlen(stdStr))))         len = tlen;
246 
247                      if ((c = ArgusParser->RaFieldDelimiter) != '\0') {
248                         printf ("N=%d%cmean=%s%cstddev=%s%cmax=%s%cmin=%s%c",
249                                      tagr->act.n, c, meanStr, c, stdStr, c, maxValStr, c, minValStr, c);
250                         printf ("median=%s%c95%%=%s", medianStr, c, percentStr);
251                      } else {
252                         printf (" N = %-6d  mean = %*s  stddev = %*s  max = %s  min = %s\n",
253                                      tagr->act.n, len, meanStr, len, stdStr, maxValStr, minValStr);
254                         printf ("           median = %*s     95%% = %s\n", len, medianStr, percentStr);
255                      }
256 
257                      if (numModes > 0) {
258                         int tlen = strlen(modeStr);
259                         if (tlen > len)
260                            len = tlen;
261 
262                         if ((c = ArgusParser->RaFieldDelimiter) != '\0')
263                            printf ("%cmode=%s", c, modeStr);
264                         else
265                            printf ("             mode = %*s\n", len, modeStr);
266                      }
267 
268                      if ((c = ArgusParser->RaFieldDelimiter) != '\0')
269                         printf ("\n");
270 
271                      if (stdStr)     free(stdStr);
272                      if (meanStr)    free(meanStr);
273                      if (medianStr)  free(medianStr);
274                      if (percentStr) free(percentStr);
275                      if (maxValStr)  free(maxValStr);
276                      if (minValStr)  free(minValStr);
277                      if (modeStr)    free(modeStr);
278                   }
279                }
280 
281                if (parser->ArgusWfileList == NULL) {
282                   if (ArgusParser->RaLabel == NULL) {
283                      char rangebuf[128], c;
284                      int size = parser->pflag;
285                      int rblen = 0;
286 
287                      if (ArgusPrintInterval)
288                         sprintf (rangebuf, "%*.*e-%*.*e ", size, size, be, size, size, be);
289                      else
290                         sprintf (rangebuf, "%*.*e ", size, size, be);
291 
292                      rblen = ((strlen(rangebuf) - strlen("Interval"))/4) * 2;
293 
294                      ArgusParser->RaLabel = ArgusGenerateLabel(ArgusParser, ns);
295 
296                      if ((c = ArgusParser->RaFieldDelimiter) != '\0') {
297                         printf ("Class%cInterval%cFreq%cRel.Freq%cCum.Freq", c, c, c, c);
298                         if (ArgusParser->RaLabel && strlen(ArgusParser->RaLabel)) {
299                            printf ("%c%s\n", c, ArgusParser->RaLabel);
300                         } else
301                            printf ("\n");
302                      } else {
303                         if (ArgusPrintInterval)
304                            printf (" Class     %*.*s%s%*.*s       Freq    Rel.Freq     Cum.Freq    %s\n",
305                                 rblen, rblen, " ", "Interval", rblen, rblen, " ", ArgusParser->RaLabel);
306                         else
307                            printf (" Class    %*.*s%s%*.*s       Freq    Rel.Freq     Cum.Freq    %s\n",
308                                 rblen, rblen, " ", "Interval", rblen, rblen, " ", ArgusParser->RaLabel);
309                      }
310                   }
311                }
312 
313                if (parser->RaHistoMetricLog) {
314                   start = parser->RaHistoStartLog;
315                } else {
316                   start = parser->RaHistoStart;
317                }
318                bsize = parser->RaHistoBinSize;
319 
320                for (i = 0; i < parser->RaHistoBins + 2; i++) {
321                   struct ArgusRecordStruct *argus = parser->RaHistoRecords[i];
322 
323                   if (i == 0) {
324                      bs = 0;
325                      be = start;
326                      if (parser->RaHistoMetricLog)
327                         be = pow(10.0, be);
328 
329                   } else {
330                      bs = (start + ((i - 1) * bsize));
331                      if (i > parser->RaHistoBins) {
332                         be = bs;
333                      } else {
334                         be = (start +  (i * bsize));
335                      }
336                      if (parser->RaHistoMetricLog) {
337                         bs = pow(10.0, bs);
338                         be = pow(10.0, be);
339                      }
340                   }
341 
342                   if ((!ArgusProcessOutLayers && ((i > 0) && (i <= parser->RaHistoBins))) || ArgusProcessOutLayers) {
343                      if (!ArgusProcessNoZero || (ArgusProcessNoZero && ((i >= start) && (i <= end)))) {
344                         if (parser->ArgusWfileList != NULL) {
345                            if (argus) {
346                               struct ArgusTimeObject *time = NULL;
347                               struct ArgusWfileStruct *wfile = NULL;
348                               struct ArgusListObjectStruct *lobj = NULL;
349                               int i, count = parser->ArgusWfileList->count;
350                               double value, frac;
351 
352                               if ((time = (void *)argus->dsrs[ARGUS_TIME_INDEX]) != NULL) {
353                                  frac = modf(bs, &value);
354                                  time->src.start.tv_sec  = value;
355                                  time->src.start.tv_usec = frac * 1000000;
356 
357                                  frac = modf(be, &value);
358                                  time->src.end.tv_sec    = value;
359                                  time->src.end.tv_usec   = frac * 1000000;
360                                  time->hdr.subtype       = ARGUS_TIME_RELATIVE_TIMESTAMP;
361                               }
362 
363                               if ((lobj = parser->ArgusWfileList->start) != NULL) {
364                                  for (i = 0; i < count; i++) {
365                                     if ((wfile = (struct ArgusWfileStruct *) lobj) != NULL) {
366                                        int pass = 1;
367                                        if (wfile->filterstr) {
368                                           struct nff_insn *wfcode = wfile->filter.bf_insns;
369                                           pass = ArgusFilterRecord (wfcode, argus);
370                                        }
371 
372                                        if (pass != 0) {
373                                           if ((parser->exceptfile == NULL) || strcmp(wfile->filename, parser->exceptfile)) {
374                                              struct ArgusRecord *argusrec = NULL;
375                                              static char sbuf[0x10000];
376                                              if ((argusrec = ArgusGenerateRecord (argus, 0L, sbuf)) != NULL) {
377 #ifdef _LITTLE_ENDIAN
378                                                 ArgusHtoN(argusrec);
379 #endif
380                                                 ArgusWriteNewLogfile (parser, argus->input, wfile, argusrec);
381                                              }
382                                           }
383                                        }
384                                     }
385 
386                                     lobj = lobj->nxt;
387                                  }
388                               }
389                            }
390 
391                         } else {
392                            int printThis = 0, size = parser->pflag;
393 
394                            bzero(buf, MAXSTRLEN);
395                            freq = 0; rel = 0.0;
396 
397                            if (argus != NULL) {
398                               struct ArgusAgrStruct *agr = (void *)argus->dsrs[ARGUS_AGR_INDEX];
399                               if (agr != NULL) {
400                                  freq =  agr->count;
401                                  rel  = (agr->count * 1.0)/(tagr->act.n * 1.0);
402                               } else {
403                                  freq = 1;
404                                  rel  = 1.0/(tagr->act.n * 1.0);
405                               }
406                               ArgusPrintRecord (parser, buf, argus, MAXSTRLEN);
407 
408                               cum    += freq;
409                               relcum += rel;
410 
411                               if (i > parser->RaHistoBins) {
412                                  if (argus && (agr && (agr->count > 0))) {
413                                     bf = be;
414                                     do {
415                                        if (parser->RaHistoMetricLog)
416                                           bf += pow(10.0, parser->RaHistoBinSize);
417                                        else
418                                           bf += parser->RaHistoBinSize;
419                                     } while (!(bf >= agr->act.maxval));
420 
421                                     printThis++;
422                                  }
423 
424                               } else {
425                                  if (!ArgusProcessNoZero || (ArgusProcessNoZero && (freq > 0.0))) {
426                                     if (i == 0) {
427                                        if (be != bs)
428                                           printThis++;
429                                     } else
430                                        printThis++;
431                                  }
432                               }
433                            } else {
434                               if (!ArgusProcessNoZero) {
435                                  if (i == 0) {
436                                     if (be != bs)
437                                        printThis++;
438                                  } else
439                                     printThis++;
440                               }
441                            }
442 
443                            if (printThis) {
444                               char c;
445                               if ((c = ArgusParser->RaFieldDelimiter) != '\0') {
446                                  if (ArgusPrintInterval) {
447                                     printf ("%d%c%e-%e%c%d%c%f%%%c%f%%",
448                                           class++, c, bs, be, c, freq, c, rel * 100.0, c, relcum * 100.0);
449                                  } else {
450                                     printf ("%d%c%e%c%d%c%f%%%c%f%%",
451                                           class++, c, bs, c, freq, c, rel * 100.0, c, relcum * 100.0);
452                                  }
453                                  if (strlen(buf)) {
454                                     printf ("%c%s\n", c, buf);
455                                  } else
456                                     printf ("\n");
457                               } else {
458                                  if (ArgusPrintInterval) {
459                                     printf ("%6d   % *.*e-%*.*e %10d   %8.4f%%    %8.4f%%    %s\n",
460                                           class++, size, size, bs, size, size, be, freq, rel * 100.0, relcum * 100.0, buf);
461                                  } else {
462                                     printf ("%6d   % *.*e %10d   %8.4f%%    %8.4f%%    %s\n",
463                                           class++, size, size, bs, freq, rel * 100.0, relcum * 100.0, buf);
464                                  }
465                               }
466                            }
467                         }
468                      }
469                   }
470                }
471             }
472          }
473 
474 #ifdef ARGUSDEBUG
475          ArgusDebug (2, "RaParseComplete(caught signal %d)\n", sig);
476 #endif
477          switch (sig) {
478             case SIGHUP:
479             case SIGINT:
480             case SIGTERM:
481             case SIGQUIT: {
482                struct ArgusWfileStruct *wfile = NULL;
483 
484                ArgusShutDown(sig);
485 
486                if (ArgusParser->ArgusWfileList != NULL) {
487                   struct ArgusListObjectStruct *lobj = NULL;
488                   int i, count = ArgusParser->ArgusWfileList->count;
489 
490                   if ((lobj = ArgusParser->ArgusWfileList->start) != NULL) {
491                      for (i = 0; i < count; i++) {
492                         if ((wfile = (struct ArgusWfileStruct *) lobj) != NULL) {
493                            if (wfile->fd != NULL) {
494 #ifdef ARGUSDEBUG
495                               ArgusDebug (2, "RaParseComplete: closing %s\n", wfile->filename);
496 #endif
497                               fflush (wfile->fd);
498                               fclose (wfile->fd);
499                               wfile->fd = NULL;
500                            }
501                         }
502                         lobj = lobj->nxt;
503                      }
504                   }
505                }
506                exit(0);
507                break;
508             }
509          }
510       }
511    }
512 }
513 
514 
515 void
ArgusClientTimeout()516 ArgusClientTimeout ()
517 {
518 #ifdef ARGUSDEBUG
519    ArgusDebug (6, "ArgusClientTimeout()\n");
520 #endif
521 }
522 
523 void
parse_arg(int argc,char ** argv)524 parse_arg (int argc, char**argv)
525 {}
526 
527 void
usage()528 usage ()
529 {
530    extern char version[];
531 
532    fprintf (stdout, "Rahisto Version %s\n", version);
533    fprintf (stdout, "usage: %s \n", ArgusParser->ArgusProgramName);
534    fprintf (stdout, "usage: %s [raoptions] -H metric bins[L]:[range | size]\n", ArgusParser->ArgusProgramName);
535 
536    fprintf (stdout, "options: -H metric bins[L][:(range | size)] \n");
537    fprintf (stdout, "            metric - any metric in argus data record\n");
538    fprintf (stdout, "              bins - number of bins to use in histogram\n");
539    fprintf (stdout, "               [L] - optionally specify logorithmic bin sizes\n");
540    fprintf (stdout, "             range - minimum and maxium values for histogram bins\n");
541    fprintf (stdout, "                syntax:  value-value\n");
542    fprintf (stdout, "                         value = %%f[umsMHD] | %%f[umKMG] depending on metric type\n");
543    fprintf (stdout, "              size - single numeric for size of each bin\n");
544    fprintf (stdout, "\n");
545    fprintf (stdout, "         -M [nozero | outlayer]\n");
546    fprintf (stdout, "             nozero - don't print bins that have zero frequency\n");
547    fprintf (stdout, "           outlayer - accumlate bins that are outside bin range\n");
548 
549 #if defined (ARGUSDEBUG)
550    fprintf (stdout, "         -D <level>         specify debug level\n");
551 #endif
552    fflush (stdout);
553 
554    exit(1);
555 }
556 
557 
558 
559 
560 int
RaSortValueBuffer(const void * item1,const void * item2)561 RaSortValueBuffer (const void *item1, const void *item2)
562 {
563    double b1 = *(double *) item1;
564    double b2 = *(double *) item2;
565    int retn = (b1 > b2) ? 1 : ((b1 == b2) ? 0 : -1);
566    return (retn);
567 }
568 
569 
570 void
RaProcessRecord(struct ArgusParserStruct * parser,struct ArgusRecordStruct * argus)571 RaProcessRecord (struct ArgusParserStruct *parser, struct ArgusRecordStruct *argus)
572 {
573    switch (argus->hdr.type & 0xF0) {
574       case ARGUS_MAR:
575       case ARGUS_EVENT: {
576          break;
577       }
578 
579       case ARGUS_NETFLOW:
580       case ARGUS_FAR: {
581          struct ArgusAggregatorStruct *agg = parser->ArgusAggregator;
582 
583          switch (parser->ArgusPassNum)  {
584             case 2: {
585                if (parser->RaHistoRangeState & ARGUS_HISTO_RANGE_UNSPECIFIED) {
586                   if (agg && (agg->RaMetricFetchAlgorithm != NULL)) {
587                      double frac, value, inte;
588                      value = agg->RaMetricFetchAlgorithm(argus);
589 
590                      if ((frac = modf(value, &inte)) != 0.0)
591                          RaValuesAreIntegers = 0;
592 
593                      if (RaValueBuffer == NULL) {
594                         if ((RaValueBuffer = malloc(sizeof(double) * RaValueBufferSize)) == NULL)
595                            ArgusLog (LOG_ERR, "RaProcessRecord: malloc error %s", strerror(errno));
596                      } else {
597                         if (RaNumberOfValues >= RaValueBufferSize) {
598                            RaValueBufferSize += 100000;
599                            if ((RaValueBuffer = realloc(RaValueBuffer, sizeof(double) * RaValueBufferSize)) == NULL)
600                               ArgusLog (LOG_ERR, "RaProcessRecord: realloc error %s", strerror(errno));
601                         }
602                      }
603 
604                      RaValueBuffer[RaNumberOfValues++] = value;
605 
606                      if (parser->RaHistoStart > value)
607                         parser->RaHistoStart = value;
608 
609                      if (parser->RaHistoEnd < value)
610                         parser->RaHistoEnd = value;
611                   }
612                }
613                break;
614             }
615 
616             case 1: {
617                double range, value, frac, inte;
618 
619                if (parser->RaHistoRangeState & ARGUS_HISTO_RANGE_UNSPECIFIED) {
620                   int cycle = 0;
621 
622                   parser->RaHistoRangeState &= ~ARGUS_HISTO_RANGE_UNSPECIFIED;
623 
624                   if (parser->RaHistoStart > 0)
625                      parser->RaHistoStart = 0.0;
626 
627                   if ((value = (parser->RaHistoEnd - parser->RaHistoStart) / (parser->RaHistoBins * 1.0)) > 0) {
628                      while (value < 10.0) {
629                         value *= 10.0;
630                         cycle++;
631                      }
632                   }
633 
634                   if ((frac = modf(value, &range)) != 0.0)
635                      range += 1.0;
636 
637                   parser->RaHistoEnd = range * parser->RaHistoBins;
638                   while (cycle > 0) {
639                      parser->RaHistoEnd /= 10.0;
640                      cycle--;
641                   }
642 
643                   parser->RaHistoBinSize = ((parser->RaHistoEnd - parser->RaHistoStart) * 1.0) / parser->RaHistoBins * 1.0;
644                }
645 
646                value = agg->RaMetricFetchAlgorithm(argus);
647                if (parser->RaHistoRangeState & ARGUS_HISTO_CAPTURE_VALUES) {
648                      if ((value >= parser->RaHistoStart) && (value <= parser->RaHistoEnd)) {
649                         if ((frac = modf(value, &inte)) != 0.0)
650                             RaValuesAreIntegers = 0;
651 
652                         if (RaValueBuffer == NULL) {
653                            if ((RaValueBuffer = malloc(sizeof(double) * RaValueBufferSize)) == NULL)
654                               ArgusLog (LOG_ERR, "RaProcessRecord: malloc error %s", strerror(errno));
655                         } else {
656                            if (RaNumberOfValues >= RaValueBufferSize) {
657                               RaValueBufferSize += 100000;
658                               if ((RaValueBuffer = realloc(RaValueBuffer, sizeof(double) * RaValueBufferSize)) == NULL)
659                                  ArgusLog (LOG_ERR, "RaProcessRecord: realloc error %s", strerror(errno));
660                            }
661                         }
662 
663                      RaValueBuffer[RaNumberOfValues++] = value;
664                   }
665                }
666 
667                if (ArgusParser && ArgusParser->ArgusAggregator) {
668                   struct ArgusAgrStruct *agr = (void *)argus->dsrs[ARGUS_AGR_INDEX];
669                   if (agr) {
670                      agr->count = 1;
671                      agr->act.maxval = value;
672                      agr->act.minval = value;
673                      agr->act.meanval = value;
674                      agr->act.n = 1;
675                      agr->act.stdev = 0;
676                   }
677                }
678 
679                if (agg && agg->RaMetricFetchAlgorithm != NULL)
680                   ArgusHistoTallyMetric (parser, argus, value);
681                break;
682             }
683          }
684       }
685    }
686 }
687 
RaSendArgusRecord(struct ArgusRecordStruct * argus)688 int RaSendArgusRecord(struct ArgusRecordStruct *argus) {return 0;}
689 
690 void ArgusWindowClose(void);
691 
ArgusWindowClose(void)692 void ArgusWindowClose(void) {
693 #ifdef ARGUSDEBUG
694    ArgusDebug (6, "ArgusWindowClose () returning\n");
695 #endif
696 }
697 
698 
699 int
RaFindModes(double * buf,long long num,double * modeValues,int len)700 RaFindModes(double *buf, long long num, double *modeValues, int len)
701 {
702    int retn = 0;
703    double value = -1;
704    int i, x, winner = 2;
705    int count = 0;
706 
707    for (i = 0; i < num; i++) {
708       if (buf[i] == value)
709          count++;
710       else {
711          if (count > winner) {
712             for (x = 0; x < retn; x++)
713                modeValues[x] = 0;
714             winner = count;
715             retn = 0;
716             modeValues[retn++] = value;
717          } else
718          if (count && (count == winner)) {
719             modeValues[retn++] = value;
720          }
721 
722          value = buf[i];
723          count = 1;
724       }
725    }
726 
727    return (retn);
728 }
729