1 /*
2 ** Zabbix
3 ** Copyright (C) 2001-2021 Zabbix SIA
4 **
5 ** This program is free software; you can redistribute it and/or modify
6 ** it under the terms of the GNU General Public License as published by
7 ** the Free Software Foundation; either version 2 of the License, or
8 ** (at your option) any later version.
9 **
10 ** This program is distributed in the hope that it will be useful,
11 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
12 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 ** GNU General Public License for more details.
14 **
15 ** You should have received a copy of the GNU General Public License
16 ** along with this program; if not, write to the Free Software
17 ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 **/
19
20 #include "zbxself.h"
21 #include "common.h"
22 #include "selfmon.h"
23
24 #ifndef _WINDOWS
25 # include "mutexs.h"
26 # include "ipc.h"
27 # include "log.h"
28
29 # define MAX_HISTORY 60
30
31 #define ZBX_SELFMON_FLUSH_DELAY (ZBX_SELFMON_DELAY * 0.5)
32
33 /* process state cache, updated only by the processes themselves */
34 typedef struct
35 {
36 /* the current usage statistics */
37 zbx_uint64_t counter[ZBX_PROCESS_STATE_COUNT];
38
39 /* ticks of the last self monitoring update */
40 clock_t ticks;
41
42 /* ticks of the last self monitoring cache flush */
43 clock_t ticks_flush;
44
45 /* the current process state (see ZBX_PROCESS_STATE_* defines) */
46 unsigned char state;
47 }
48 zxb_stat_process_cache_t;
49
50 /* process state statistics */
51 typedef struct
52 {
53 /* historical process state data */
54 unsigned short h_counter[ZBX_PROCESS_STATE_COUNT][MAX_HISTORY];
55
56 /* process state data for the current data gathering cycle */
57 unsigned short counter[ZBX_PROCESS_STATE_COUNT];
58
59 /* the process state that was already applied to the historical state data */
60 zbx_uint64_t counter_used[ZBX_PROCESS_STATE_COUNT];
61
62 /* the process state cache */
63 zxb_stat_process_cache_t cache;
64 }
65 zbx_stat_process_t;
66
67 typedef struct
68 {
69 zbx_stat_process_t **process;
70 int first;
71 int count;
72
73 /* number of ticks per second */
74 int ticks_per_sec;
75
76 /* ticks of the last self monitoring sync (data gathering) */
77 clock_t ticks_sync;
78 }
79 zbx_selfmon_collector_t;
80
81 static zbx_selfmon_collector_t *collector = NULL;
82 static int shm_id;
83
84 # define LOCK_SM zbx_mutex_lock(sm_lock)
85 # define UNLOCK_SM zbx_mutex_unlock(sm_lock)
86
87 static zbx_mutex_t sm_lock = ZBX_MUTEX_NULL;
88 #endif
89
90 extern char *CONFIG_FILE;
91 extern int CONFIG_POLLER_FORKS;
92 extern int CONFIG_UNREACHABLE_POLLER_FORKS;
93 extern int CONFIG_IPMIPOLLER_FORKS;
94 extern int CONFIG_PINGER_FORKS;
95 extern int CONFIG_JAVAPOLLER_FORKS;
96 extern int CONFIG_HTTPPOLLER_FORKS;
97 extern int CONFIG_TRAPPER_FORKS;
98 extern int CONFIG_SNMPTRAPPER_FORKS;
99 extern int CONFIG_PROXYPOLLER_FORKS;
100 extern int CONFIG_ESCALATOR_FORKS;
101 extern int CONFIG_HISTSYNCER_FORKS;
102 extern int CONFIG_DISCOVERER_FORKS;
103 extern int CONFIG_ALERTER_FORKS;
104 extern int CONFIG_TIMER_FORKS;
105 extern int CONFIG_HOUSEKEEPER_FORKS;
106 extern int CONFIG_DATASENDER_FORKS;
107 extern int CONFIG_CONFSYNCER_FORKS;
108 extern int CONFIG_HEARTBEAT_FORKS;
109 extern int CONFIG_SELFMON_FORKS;
110 extern int CONFIG_VMWARE_FORKS;
111 extern int CONFIG_COLLECTOR_FORKS;
112 extern int CONFIG_PASSIVE_FORKS;
113 extern int CONFIG_ACTIVE_FORKS;
114 extern int CONFIG_TASKMANAGER_FORKS;
115 extern int CONFIG_IPMIMANAGER_FORKS;
116 extern int CONFIG_ALERTMANAGER_FORKS;
117 extern int CONFIG_PREPROCMAN_FORKS;
118 extern int CONFIG_PREPROCESSOR_FORKS;
119 extern int CONFIG_LLDMANAGER_FORKS;
120 extern int CONFIG_LLDWORKER_FORKS;
121 extern int CONFIG_ALERTDB_FORKS;
122 extern int CONFIG_HISTORYPOLLER_FORKS;
123 extern int CONFIG_AVAILMAN_FORKS;
124
125 extern unsigned char process_type;
126 extern int process_num;
127
128 /******************************************************************************
129 * *
130 * Function: get_process_type_forks *
131 * *
132 * Purpose: Returns number of processes depending on process type *
133 * *
134 * Parameters: proc_type - [IN] process type; ZBX_PROCESS_TYPE_* *
135 * *
136 * Return value: number of processes *
137 * *
138 * Author: Alexander Vladishev *
139 * *
140 ******************************************************************************/
get_process_type_forks(unsigned char proc_type)141 int get_process_type_forks(unsigned char proc_type)
142 {
143 switch (proc_type)
144 {
145 case ZBX_PROCESS_TYPE_POLLER:
146 return CONFIG_POLLER_FORKS;
147 case ZBX_PROCESS_TYPE_UNREACHABLE:
148 return CONFIG_UNREACHABLE_POLLER_FORKS;
149 case ZBX_PROCESS_TYPE_IPMIPOLLER:
150 return CONFIG_IPMIPOLLER_FORKS;
151 case ZBX_PROCESS_TYPE_PINGER:
152 return CONFIG_PINGER_FORKS;
153 case ZBX_PROCESS_TYPE_JAVAPOLLER:
154 return CONFIG_JAVAPOLLER_FORKS;
155 case ZBX_PROCESS_TYPE_HTTPPOLLER:
156 return CONFIG_HTTPPOLLER_FORKS;
157 case ZBX_PROCESS_TYPE_TRAPPER:
158 return CONFIG_TRAPPER_FORKS;
159 case ZBX_PROCESS_TYPE_SNMPTRAPPER:
160 return CONFIG_SNMPTRAPPER_FORKS;
161 case ZBX_PROCESS_TYPE_PROXYPOLLER:
162 return CONFIG_PROXYPOLLER_FORKS;
163 case ZBX_PROCESS_TYPE_ESCALATOR:
164 return CONFIG_ESCALATOR_FORKS;
165 case ZBX_PROCESS_TYPE_HISTSYNCER:
166 return CONFIG_HISTSYNCER_FORKS;
167 case ZBX_PROCESS_TYPE_DISCOVERER:
168 return CONFIG_DISCOVERER_FORKS;
169 case ZBX_PROCESS_TYPE_ALERTER:
170 return CONFIG_ALERTER_FORKS;
171 case ZBX_PROCESS_TYPE_TIMER:
172 return CONFIG_TIMER_FORKS;
173 case ZBX_PROCESS_TYPE_HOUSEKEEPER:
174 return CONFIG_HOUSEKEEPER_FORKS;
175 case ZBX_PROCESS_TYPE_DATASENDER:
176 return CONFIG_DATASENDER_FORKS;
177 case ZBX_PROCESS_TYPE_CONFSYNCER:
178 return CONFIG_CONFSYNCER_FORKS;
179 case ZBX_PROCESS_TYPE_HEARTBEAT:
180 return CONFIG_HEARTBEAT_FORKS;
181 case ZBX_PROCESS_TYPE_SELFMON:
182 return CONFIG_SELFMON_FORKS;
183 case ZBX_PROCESS_TYPE_VMWARE:
184 return CONFIG_VMWARE_FORKS;
185 case ZBX_PROCESS_TYPE_COLLECTOR:
186 return CONFIG_COLLECTOR_FORKS;
187 case ZBX_PROCESS_TYPE_LISTENER:
188 return CONFIG_PASSIVE_FORKS;
189 case ZBX_PROCESS_TYPE_ACTIVE_CHECKS:
190 return CONFIG_ACTIVE_FORKS;
191 case ZBX_PROCESS_TYPE_TASKMANAGER:
192 return CONFIG_TASKMANAGER_FORKS;
193 case ZBX_PROCESS_TYPE_IPMIMANAGER:
194 return CONFIG_IPMIMANAGER_FORKS;
195 case ZBX_PROCESS_TYPE_ALERTMANAGER:
196 return CONFIG_ALERTMANAGER_FORKS;
197 case ZBX_PROCESS_TYPE_PREPROCMAN:
198 return CONFIG_PREPROCMAN_FORKS;
199 case ZBX_PROCESS_TYPE_PREPROCESSOR:
200 return CONFIG_PREPROCESSOR_FORKS;
201 case ZBX_PROCESS_TYPE_LLDMANAGER:
202 return CONFIG_LLDMANAGER_FORKS;
203 case ZBX_PROCESS_TYPE_LLDWORKER:
204 return CONFIG_LLDWORKER_FORKS;
205 case ZBX_PROCESS_TYPE_ALERTSYNCER:
206 return CONFIG_ALERTDB_FORKS;
207 case ZBX_PROCESS_TYPE_HISTORYPOLLER:
208 return CONFIG_HISTORYPOLLER_FORKS;
209 case ZBX_PROCESS_TYPE_AVAILMAN:
210 return CONFIG_AVAILMAN_FORKS;
211 }
212
213 return get_component_process_type_forks(proc_type);
214 }
215
216 #ifndef _WINDOWS
217 /******************************************************************************
218 * *
219 * Function: init_selfmon_collector *
220 * *
221 * Purpose: Initialize structures and prepare state *
222 * for self-monitoring collector *
223 * *
224 * Author: Alexander Vladishev *
225 * *
226 ******************************************************************************/
init_selfmon_collector(char ** error)227 int init_selfmon_collector(char **error)
228 {
229 size_t sz, sz_array, sz_process[ZBX_PROCESS_TYPE_COUNT], sz_total;
230 char *p;
231 unsigned char proc_type;
232 int proc_num, process_forks, ret = FAIL;
233
234 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
235
236 sz_total = sz = sizeof(zbx_selfmon_collector_t);
237 sz_total += sz_array = sizeof(zbx_stat_process_t *) * ZBX_PROCESS_TYPE_COUNT;
238
239 for (proc_type = 0; ZBX_PROCESS_TYPE_COUNT > proc_type; proc_type++)
240 sz_total += sz_process[proc_type] = sizeof(zbx_stat_process_t) * get_process_type_forks(proc_type);
241
242 zabbix_log(LOG_LEVEL_DEBUG, "%s() size:" ZBX_FS_SIZE_T, __func__, (zbx_fs_size_t)sz_total);
243
244 if (SUCCEED != zbx_mutex_create(&sm_lock, ZBX_MUTEX_SELFMON, error))
245 {
246 zbx_error("unable to create mutex for a self-monitoring collector");
247 exit(EXIT_FAILURE);
248 }
249
250 if (-1 == (shm_id = shmget(IPC_PRIVATE, sz_total, 0600)))
251 {
252 *error = zbx_strdup(*error, "cannot allocate shared memory for a self-monitoring collector");
253 goto out;
254 }
255
256 if ((void *)(-1) == (p = (char *)shmat(shm_id, NULL, 0)))
257 {
258 *error = zbx_dsprintf(*error, "cannot attach shared memory for a self-monitoring collector: %s",
259 zbx_strerror(errno));
260 goto out;
261 }
262
263 if (-1 == shmctl(shm_id, IPC_RMID, NULL))
264 zbx_error("cannot mark shared memory %d for destruction: %s", shm_id, zbx_strerror(errno));
265
266 collector = (zbx_selfmon_collector_t *)p; p += sz;
267 collector->process = (zbx_stat_process_t **)p; p += sz_array;
268 collector->ticks_per_sec = sysconf(_SC_CLK_TCK);
269 collector->ticks_sync = 0;
270
271 for (proc_type = 0; ZBX_PROCESS_TYPE_COUNT > proc_type; proc_type++)
272 {
273 collector->process[proc_type] = (zbx_stat_process_t *)p; p += sz_process[proc_type];
274 memset(collector->process[proc_type], 0, sz_process[proc_type]);
275
276 process_forks = get_process_type_forks(proc_type);
277 for (proc_num = 0; proc_num < process_forks; proc_num++)
278 {
279 collector->process[proc_type][proc_num].cache.state = ZBX_PROCESS_STATE_IDLE;
280 }
281 }
282
283 ret = SUCCEED;
284 out:
285 zabbix_log(LOG_LEVEL_DEBUG, "End of %s() collector:%p", __func__, (void *)collector);
286
287 return ret;
288 }
289
290 /******************************************************************************
291 * *
292 * Function: free_selfmon_collector *
293 * *
294 * Purpose: Free memory allocated for self-monitoring collector *
295 * *
296 * Author: Alexander Vladishev *
297 * *
298 ******************************************************************************/
free_selfmon_collector(void)299 void free_selfmon_collector(void)
300 {
301 zabbix_log(LOG_LEVEL_DEBUG, "In %s() collector:%p", __func__, (void *)collector);
302
303 if (NULL == collector)
304 return;
305
306 LOCK_SM;
307
308 collector = NULL;
309
310 if (-1 == shmctl(shm_id, IPC_RMID, 0))
311 {
312 zabbix_log(LOG_LEVEL_WARNING, "cannot remove shared memory for self-monitoring collector: %s",
313 zbx_strerror(errno));
314 }
315
316 UNLOCK_SM;
317
318 zbx_mutex_destroy(&sm_lock);
319
320 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
321 }
322
323 /******************************************************************************
324 * *
325 * Function: update_selfmon_counter *
326 * *
327 * Parameters: state - [IN] new process state; ZBX_PROCESS_STATE_* *
328 * *
329 * Author: Alexander Vladishev *
330 * *
331 ******************************************************************************/
update_selfmon_counter(unsigned char state)332 void update_selfmon_counter(unsigned char state)
333 {
334 zbx_stat_process_t *process;
335 clock_t ticks;
336 struct tms buf;
337 int i;
338
339 if (ZBX_PROCESS_TYPE_UNKNOWN == process_type)
340 return;
341
342 process = &collector->process[process_type][process_num - 1];
343
344 if (-1 == (ticks = times(&buf)))
345 {
346 zabbix_log(LOG_LEVEL_WARNING, "cannot get process times: %s", zbx_strerror(errno));
347 process->cache.state = state;
348 return;
349 }
350
351 if (0 == process->cache.ticks_flush)
352 {
353 process->cache.ticks_flush = ticks;
354 process->cache.state = state;
355 process->cache.ticks = ticks;
356 return;
357 }
358
359 /* update process statistics in local cache */
360 process->cache.counter[process->cache.state] += ticks - process->cache.ticks;
361
362 if (ZBX_SELFMON_FLUSH_DELAY < (double)(ticks - process->cache.ticks_flush) / collector->ticks_per_sec)
363 {
364 LOCK_SM;
365
366 for (i = 0; i < ZBX_PROCESS_STATE_COUNT; i++)
367 {
368 /* If process did not update selfmon counter during one self monitoring data */
369 /* collection interval, then self monitor will collect statistics based on the */
370 /* current process state and the ticks passed since last self monitoring data */
371 /* collection. This value is stored in counter_used and the local statistics */
372 /* must be adjusted by this (already collected) value. */
373 if (process->cache.counter[i] > process->counter_used[i])
374 {
375 process->cache.counter[i] -= process->counter_used[i];
376 process->counter[i] += process->cache.counter[i];
377 }
378
379 /* reset current cache statistics */
380 process->counter_used[i] = 0;
381 process->cache.counter[i] = 0;
382 }
383
384 process->cache.ticks_flush = ticks;
385
386 UNLOCK_SM;
387 }
388
389 /* update local self monitoring cache */
390 process->cache.state = state;
391 process->cache.ticks = ticks;
392 }
393
394 /******************************************************************************
395 * *
396 * Function: collect_selfmon_stats *
397 * *
398 * Author: Alexander Vladishev *
399 * *
400 ******************************************************************************/
collect_selfmon_stats(void)401 void collect_selfmon_stats(void)
402 {
403 zbx_stat_process_t *process;
404 clock_t ticks, ticks_done;
405 struct tms buf;
406 unsigned char proc_type, i;
407 int proc_num, process_forks, index, last;
408
409 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
410
411 if (-1 == (ticks = times(&buf)))
412 {
413 zabbix_log(LOG_LEVEL_WARNING, "cannot get process times: %s", zbx_strerror(errno));
414 goto out;
415 }
416
417 if (0 == collector->ticks_sync)
418 {
419 collector->ticks_sync = ticks;
420 goto out;
421 }
422
423 if (MAX_HISTORY <= (index = collector->first + collector->count))
424 index -= MAX_HISTORY;
425
426 if (collector->count < MAX_HISTORY)
427 collector->count++;
428 else if (++collector->first == MAX_HISTORY)
429 collector->first = 0;
430
431 if (0 > (last = index - 1))
432 last += MAX_HISTORY;
433
434 LOCK_SM;
435
436 ticks_done = ticks - collector->ticks_sync;
437
438 for (proc_type = 0; proc_type < ZBX_PROCESS_TYPE_COUNT; proc_type++)
439 {
440 process_forks = get_process_type_forks(proc_type);
441 for (proc_num = 0; proc_num < process_forks; proc_num++)
442 {
443 process = &collector->process[proc_type][proc_num];
444
445 if (process->cache.ticks_flush < collector->ticks_sync)
446 {
447 /* If the process local cache was not flushed during the last self monitoring */
448 /* data collection interval update the process statistics based on the current */
449 /* process state and ticks passed during the collection interval. Store this */
450 /* value so the process local self monitoring cache can be adjusted before */
451 /* flushing. */
452 process->counter[process->cache.state] += ticks_done;
453 process->counter_used[process->cache.state] += ticks_done;
454 }
455
456 for (i = 0; i < ZBX_PROCESS_STATE_COUNT; i++)
457 {
458 /* The data is gathered as ticks spent in corresponding states during the */
459 /* self monitoring data collection interval. But in history the data are */
460 /* stored as relative values. To achieve it we add the collected data to */
461 /* the last values. */
462 process->h_counter[i][index] = process->h_counter[i][last] + process->counter[i];
463 process->counter[i] = 0;
464 }
465 }
466 }
467
468 collector->ticks_sync = ticks;
469
470 UNLOCK_SM;
471 out:
472 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
473 }
474
475 /******************************************************************************
476 * *
477 * Function: get_selfmon_stats *
478 * *
479 * Purpose: calculate statistics for selected process *
480 * *
481 * Parameters: proc_type - [IN] type of process; ZBX_PROCESS_TYPE_* *
482 * aggr_func - [IN] one of ZBX_AGGR_FUNC_* *
483 * proc_num - [IN] process number; 1 - first process; *
484 * 0 - all processes *
485 * state - [IN] process state; ZBX_PROCESS_STATE_* *
486 * value - [OUT] a pointer to a variable that receives *
487 * requested statistics *
488 * *
489 * Author: Alexander Vladishev *
490 * *
491 ******************************************************************************/
get_selfmon_stats(unsigned char proc_type,unsigned char aggr_func,int proc_num,unsigned char state,double * value)492 void get_selfmon_stats(unsigned char proc_type, unsigned char aggr_func, int proc_num, unsigned char state,
493 double *value)
494 {
495 unsigned int total = 0, counter = 0;
496 unsigned char s;
497 int process_forks, current;
498
499 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
500
501 process_forks = get_process_type_forks(proc_type);
502
503 switch (aggr_func)
504 {
505 case ZBX_AGGR_FUNC_ONE:
506 assert(0 < proc_num && proc_num <= process_forks);
507 process_forks = proc_num--;
508 break;
509 case ZBX_AGGR_FUNC_AVG:
510 case ZBX_AGGR_FUNC_MAX:
511 case ZBX_AGGR_FUNC_MIN:
512 assert(0 == proc_num && 0 < process_forks);
513 break;
514 default:
515 assert(0);
516 }
517
518 LOCK_SM;
519
520 if (1 >= collector->count)
521 goto unlock;
522
523 if (MAX_HISTORY <= (current = (collector->first + collector->count - 1)))
524 current -= MAX_HISTORY;
525
526 for (; proc_num < process_forks; proc_num++)
527 {
528 zbx_stat_process_t *process;
529 unsigned int one_total = 0, one_counter;
530
531 process = &collector->process[proc_type][proc_num];
532
533 for (s = 0; s < ZBX_PROCESS_STATE_COUNT; s++)
534 {
535 one_total += (unsigned short)(process->h_counter[s][current] -
536 process->h_counter[s][collector->first]);
537 }
538
539 one_counter = (unsigned short)(process->h_counter[state][current] -
540 process->h_counter[state][collector->first]);
541
542 switch (aggr_func)
543 {
544 case ZBX_AGGR_FUNC_ONE:
545 case ZBX_AGGR_FUNC_AVG:
546 total += one_total;
547 counter += one_counter;
548 break;
549 case ZBX_AGGR_FUNC_MAX:
550 if (0 == proc_num || one_counter > counter)
551 {
552 counter = one_counter;
553 total = one_total;
554 }
555 break;
556 case ZBX_AGGR_FUNC_MIN:
557 if (0 == proc_num || one_counter < counter)
558 {
559 counter = one_counter;
560 total = one_total;
561 }
562 break;
563 }
564 }
565
566 unlock:
567 UNLOCK_SM;
568
569 *value = (0 == total ? 0 : 100. * (double)counter / (double)total);
570
571 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
572 }
573
574 /******************************************************************************
575 * *
576 * Function: zbx_get_all_process_stats *
577 * *
578 * Purpose: retrieves internal metrics of all running processes based on *
579 * process type *
580 * *
581 * Parameters: stats - [OUT] process metrics *
582 * *
583 ******************************************************************************/
zbx_get_all_process_stats(zbx_process_info_t * stats)584 int zbx_get_all_process_stats(zbx_process_info_t *stats)
585 {
586 int current, ret = FAIL;
587 unsigned char proc_type;
588
589 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
590
591 LOCK_SM;
592
593 if (1 >= collector->count)
594 goto unlock;
595
596 if (MAX_HISTORY <= (current = (collector->first + collector->count - 1)))
597 current -= MAX_HISTORY;
598
599 for (proc_type = 0; proc_type < ZBX_PROCESS_TYPE_COUNT; proc_type++)
600 {
601 int proc_num;
602 unsigned int total_avg = 0, counter_avg_busy = 0, counter_avg_idle = 0,
603 total_max = 0, counter_max_busy = 0, counter_max_idle = 0,
604 total_min = 0, counter_min_busy = 0, counter_min_idle = 0;
605
606 stats[proc_type].count = get_process_type_forks(proc_type);
607
608 for (proc_num = 0; proc_num < stats[proc_type].count; proc_num++)
609 {
610 zbx_stat_process_t *process;
611 unsigned int one_total = 0, busy_counter, idle_counter;
612 unsigned char s;
613
614 process = &collector->process[proc_type][proc_num];
615
616 for (s = 0; s < ZBX_PROCESS_STATE_COUNT; s++)
617 {
618 one_total += (unsigned short)(process->h_counter[s][current] -
619 process->h_counter[s][collector->first]);
620 }
621
622 busy_counter = (unsigned short)(process->h_counter[ZBX_PROCESS_STATE_BUSY][current] -
623 process->h_counter[ZBX_PROCESS_STATE_BUSY][collector->first]);
624
625 idle_counter = (unsigned short)(process->h_counter[ZBX_PROCESS_STATE_IDLE][current] -
626 process->h_counter[ZBX_PROCESS_STATE_IDLE][collector->first]);
627
628 total_avg += one_total;
629 counter_avg_busy += busy_counter;
630 counter_avg_idle += idle_counter;
631
632 if (0 == proc_num || busy_counter > counter_max_busy)
633 {
634 counter_max_busy = busy_counter;
635 total_max = one_total;
636 }
637
638 if (0 == proc_num || idle_counter > counter_max_idle)
639 {
640 counter_max_idle = idle_counter;
641 total_max = one_total;
642 }
643
644 if (0 == proc_num || busy_counter < counter_min_busy)
645 {
646 counter_min_busy = busy_counter;
647 total_min = one_total;
648 }
649
650 if (0 == proc_num || idle_counter < counter_min_idle)
651 {
652 counter_min_idle = idle_counter;
653 total_min = one_total;
654 }
655 }
656
657 stats[proc_type].busy_avg = (0 == total_avg ? 0 : 100. * (double)counter_avg_busy / (double)total_avg);
658 stats[proc_type].busy_max = (0 == total_max ? 0 : 100. * (double)counter_max_busy / (double)total_max);
659 stats[proc_type].busy_min = (0 == total_min ? 0 : 100. * (double)counter_min_busy / (double)total_min);
660
661 stats[proc_type].idle_avg = (0 == total_avg ? 0 : 100. * (double)counter_avg_idle / (double)total_avg);
662 stats[proc_type].idle_max = (0 == total_max ? 0 : 100. * (double)counter_max_idle / (double)total_max);
663 stats[proc_type].idle_min = (0 == total_min ? 0 : 100. * (double)counter_min_idle / (double)total_min);
664 }
665
666 ret = SUCCEED;
667 unlock:
668 UNLOCK_SM;
669
670 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret));
671
672 return ret;
673 }
674
675 static int sleep_remains;
676
677 /******************************************************************************
678 * *
679 * Function: zbx_sleep_loop *
680 * *
681 * Purpose: sleeping process *
682 * *
683 * Parameters: sleeptime - [IN] required sleeptime, in seconds *
684 * *
685 * Author: Alexander Vladishev *
686 * *
687 ******************************************************************************/
zbx_sleep_loop(int sleeptime)688 void zbx_sleep_loop(int sleeptime)
689 {
690 if (0 >= sleeptime)
691 return;
692
693 sleep_remains = sleeptime;
694
695 update_selfmon_counter(ZBX_PROCESS_STATE_IDLE);
696
697 do
698 {
699 sleep(1);
700 }
701 while (0 < --sleep_remains);
702
703 update_selfmon_counter(ZBX_PROCESS_STATE_BUSY);
704 }
705
zbx_sleep_forever(void)706 void zbx_sleep_forever(void)
707 {
708 sleep_remains = 1;
709
710 update_selfmon_counter(ZBX_PROCESS_STATE_IDLE);
711
712 do
713 {
714 sleep(1);
715 }
716 while (0 != sleep_remains);
717
718 update_selfmon_counter(ZBX_PROCESS_STATE_BUSY);
719 }
720
zbx_wakeup(void)721 void zbx_wakeup(void)
722 {
723 sleep_remains = 0;
724 }
725
zbx_sleep_get_remainder(void)726 int zbx_sleep_get_remainder(void)
727 {
728 return sleep_remains;
729 }
730 #endif
731