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