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